├── .bithoundrc
├── .gitignore
├── .npmignore
├── .travis.yml
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── dist
├── MeteorObservable.d.ts
├── MeteorObservable.js
├── MeteorObservable.js.map
├── ObservableCollection.d.ts
├── ObservableCollection.js
├── ObservableCollection.js.map
├── ObservableCursor.d.ts
├── ObservableCursor.js
├── ObservableCursor.js.map
├── bundles
│ └── index.umd.js
├── index.d.ts
├── index.js
├── index.js.map
├── utils.d.ts
├── utils.js
├── utils.js.map
├── zone.d.ts
├── zone.js
└── zone.js.map
├── docs
├── MeteorObservable.md
├── ObservableCollection.md
└── ObservableCursor.md
├── examples
└── angular2
│ ├── .gitignore
│ ├── .meteor
│ ├── .finished-upgraders
│ ├── .gitignore
│ ├── .id
│ ├── packages
│ ├── platforms
│ ├── release
│ └── versions
│ ├── both
│ ├── collections
│ │ └── demo.collection.ts
│ └── models
│ │ └── demo.model.ts
│ ├── client
│ ├── imports
│ │ └── app
│ │ │ ├── app.component.html
│ │ │ ├── app.component.scss
│ │ │ ├── app.component.ts
│ │ │ ├── app.module.ts
│ │ │ └── index.ts
│ ├── index.html
│ ├── main.ts
│ └── styles
│ │ └── main.scss
│ ├── package.json
│ ├── server
│ ├── imports
│ │ └── server-main
│ │ │ └── main.ts
│ └── main.ts
│ ├── tsconfig.json
│ └── typings.d.ts
├── generate-docs.sh
├── package.json
├── rollup.config.js
├── src
├── MeteorObservable.ts
├── ObservableCollection.ts
├── ObservableCursor.ts
├── index.ts
├── utils.ts
└── zone.ts
├── tests
├── .meteor
│ ├── .finished-upgraders
│ ├── .gitignore
│ ├── .id
│ ├── packages
│ ├── platforms
│ ├── release
│ └── versions
├── client
│ └── unit
│ │ ├── meteor-observable.spec.ts
│ │ ├── observable-collection.spec.ts
│ │ ├── observable-cursor.spec.ts
│ │ └── zone-operator.spec.ts
├── package-lock.json
├── package.json
├── server
│ └── lib
│ │ └── create-test-method.spec.ts
├── tsconfig.json
└── yarn.lock
├── tsconfig.json
├── tslint.json
└── yarn.lock
/.bithoundrc:
--------------------------------------------------------------------------------
1 | {
2 | "ignore": [
3 | "**/node_modules/**",
4 | "**/dist/**",
5 | "**/docs/**",
6 | "**/examples/**"
7 | ],
8 | "test": [
9 | "**/test/**",
10 | "**/tests/**",
11 | "**/spec/**",
12 | "**/specs/**",
13 | "**/*.test.ts",
14 | "**/*.test.js",
15 | "**/*.spec.js",
16 | "**/*.spec.ts"
17 | ],
18 | "critics": {
19 | "lint": {"engine": "tslint"}
20 | },
21 | "dependencies": {
22 | "mute": [
23 | "rxjs",
24 | "zone.js",
25 | "jsdoc-to-markdown"
26 | ],
27 | "unused-ignores": [
28 | "tslint",
29 | "validate-commit-msg",
30 | "typescript",
31 | "rollup",
32 | "ghooks",
33 | "es6-shim",
34 | "conventional-changelog",
35 | "conventional-changelog-cli",
36 | "zone.js",
37 | "reflect-metadata",
38 | "@types/*"
39 | ]
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .node_modules
3 | .idea
4 | typings
5 | .npm
6 | npm-debug.log
7 | package-lock.json
8 | *.log
9 |
10 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | examples
2 | tests
3 | typings
4 | src
5 | rollup.config.js
6 | run_tests.sh
7 | tsconfig.json
8 | tslint.json
9 | typings.d.ts
10 | generate-docs.sh
11 | .travis.yml
12 | .bithoundrc
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: required
2 | language: node_js
3 | node_js:
4 | - "6"
5 | services:
6 | - mongodb
7 | before_install:
8 | - curl https://install.meteor.com | /bin/sh
9 | - rm -rf node_modules
10 |
11 | install:
12 | - git clean -fXd
13 | - npm install -g phantomjs-prebuilt tslint typescript rollup
14 | - npm install
15 | - cd tests && meteor npm rebuild && cd ..
16 |
17 | script:
18 | - npm run test-ci
19 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | ## 0.4.9 (2018-03-17)
3 |
4 | * bug fixes ([85383ed](https://github.com/Urigo/mongo-rxjs-observable/commit/85383ed))
5 | * bump version ([da88a37](https://github.com/Urigo/mongo-rxjs-observable/commit/da88a37))
6 | * change rxjs imports to best practice for better performance ([f4887a5](https://github.com/Urigo/mongo-rxjs-observable/commit/f4887a5))
7 | * fix version bump ([6b8fead](https://github.com/Urigo/mongo-rxjs-observable/commit/6b8fead))
8 | * fixes ([05d1e67](https://github.com/Urigo/mongo-rxjs-observable/commit/05d1e67))
9 | * make dependencies compatible with both angular and meteor ([bcdc720](https://github.com/Urigo/mongo-rxjs-observable/commit/bcdc720))
10 | * removed old tslint config ([e6530b2](https://github.com/Urigo/mongo-rxjs-observable/commit/e6530b2))
11 | * Replace 'meteor-typings' with '@types/meteor' ([791ba31](https://github.com/Urigo/mongo-rxjs-observable/commit/791ba31))
12 | * rollup configuration fixed ([23d1ea5](https://github.com/Urigo/mongo-rxjs-observable/commit/23d1ea5))
13 | * Store subscriptionIds to handle re-subscriptions ([8ddd5f1](https://github.com/Urigo/mongo-rxjs-observable/commit/8ddd5f1))
14 | * try to fix meteor typings issue ([e1eb411](https://github.com/Urigo/mongo-rxjs-observable/commit/e1eb411))
15 | * Update documentation for MeteorObservable ([c7816ba](https://github.com/Urigo/mongo-rxjs-observable/commit/c7816ba))
16 | * update README.md ([a67078c](https://github.com/Urigo/mongo-rxjs-observable/commit/a67078c))
17 | * update rollup.config.js ([a5c4565](https://github.com/Urigo/mongo-rxjs-observable/commit/a5c4565))
18 | * update test script ([e0ff15c](https://github.com/Urigo/mongo-rxjs-observable/commit/e0ff15c))
19 | * updated all deps and some minor fixes ([58b0fda](https://github.com/Urigo/mongo-rxjs-observable/commit/58b0fda))
20 | * updated changelog ([cb9697f](https://github.com/Urigo/mongo-rxjs-observable/commit/cb9697f))
21 | * refactor(deps): renovate pin dependencies packages ([b967636](https://github.com/Urigo/mongo-rxjs-observable/commit/b967636))
22 | * fix: return empty array when find yield no results ([b09c6af](https://github.com/Urigo/mongo-rxjs-observable/commit/b09c6af))
23 |
24 |
25 | ## 0.4.8 (2017-09-13)
26 | * updated all dependencies
27 | * updated tests project to latest Meteor version
28 | * Fix: return empty array when find yield no results [#103](https://github.com/Urigo/meteor-rxjs/pull/103)
29 | * Fix multiple MeteorObservable.subscribe calls with identical arguments [#76](https://github.com/Urigo/meteor-rxjs/pull/76)
30 |
31 |
32 | ## 0.4.7 (2016-12-21)
33 |
34 | * chore: add ref to the main ES6 module in package.json (for bundling) ([b5f7bab](https://github.com/Urigo/mongo-rxjs-observable/commit/b5f7bab))
35 | * chore: remove browser from package.json (not needed) ([6b30a15](https://github.com/Urigo/mongo-rxjs-observable/commit/6b30a15))
36 | * chore(bithound): fixed unused ([7353c76](https://github.com/Urigo/mongo-rxjs-observable/commit/7353c76))
37 | * chore(bithound): ignore examples directory ([00f6712](https://github.com/Urigo/mongo-rxjs-observable/commit/00f6712))
38 | * chore(bithound): ignore zone.js ([2364061](https://github.com/Urigo/mongo-rxjs-observable/commit/2364061))
39 | * chore(build): fixed build ([28ac86a](https://github.com/Urigo/mongo-rxjs-observable/commit/28ac86a))
40 | * chore(dependencies): cleanup and generated dist ([f4debe4](https://github.com/Urigo/mongo-rxjs-observable/commit/f4debe4))
41 | * chore(dependencies): updated tslint ([d979b06](https://github.com/Urigo/mongo-rxjs-observable/commit/d979b06))
42 | * chore(deps): update rxjs ([48967df](https://github.com/Urigo/mongo-rxjs-observable/commit/48967df))
43 | * chore(license): add license file ([edf365c](https://github.com/Urigo/mongo-rxjs-observable/commit/edf365c))
44 | * chore(package): update @types/mocha to version 2.2.34 ([5de0f13](https://github.com/Urigo/mongo-rxjs-observable/commit/5de0f13))
45 | * chore(package): update @types/underscore to version 1.7.34 ([54b6e15](https://github.com/Urigo/mongo-rxjs-observable/commit/54b6e15))
46 | * chore(package): update @types/underscore to version 1.7.35 ([2962f0e](https://github.com/Urigo/mongo-rxjs-observable/commit/2962f0e))
47 | * chore(package): update @types/underscore to version 1.7.36 ([f863cc9](https://github.com/Urigo/mongo-rxjs-observable/commit/f863cc9))
48 | * chore(package): update es6-shim to version 0.35.2 ([7a69239](https://github.com/Urigo/mongo-rxjs-observable/commit/7a69239))
49 | * chore(package): update rollup to version 0.36.4 ([5f727a5](https://github.com/Urigo/mongo-rxjs-observable/commit/5f727a5))
50 | * chore(package): update rollup to version 0.37.0 ([d00522e](https://github.com/Urigo/mongo-rxjs-observable/commit/d00522e))
51 | * chore(package): update rollup to version 0.37.1 ([24cd297](https://github.com/Urigo/mongo-rxjs-observable/commit/24cd297))
52 | * chore(package): update tslint to version 4.0.1 ([36aecea](https://github.com/Urigo/mongo-rxjs-observable/commit/36aecea))
53 | * chore(package): update tslint to version 4.1.0 ([cb0d60a](https://github.com/Urigo/mongo-rxjs-observable/commit/cb0d60a))
54 | * chore(package): update typescript to version 2.0.10 ([daacf21](https://github.com/Urigo/mongo-rxjs-observable/commit/daacf21))
55 | * chore(package): update typescript to version 2.1.4 ([1226d43](https://github.com/Urigo/mongo-rxjs-observable/commit/1226d43))
56 | * chore(package): update zone.js to version 0.7.3 ([4aec29a](https://github.com/Urigo/mongo-rxjs-observable/commit/4aec29a))
57 | * chore(package): update zone.js to version 0.7.4 ([4a322e3](https://github.com/Urigo/mongo-rxjs-observable/commit/4a322e3))
58 | * chore(sourcemap): added missing source map files ([4d62b9c](https://github.com/Urigo/mongo-rxjs-observable/commit/4d62b9c))
59 | * chore(types): some minor fixes for new typings ([cc7215c](https://github.com/Urigo/mongo-rxjs-observable/commit/cc7215c))
60 | * release(0.4.6): release new version ([e7210b3](https://github.com/Urigo/mongo-rxjs-observable/commit/e7210b3))
61 | * tests(version): updated meteor version for tests project ([a041b6d](https://github.com/Urigo/mongo-rxjs-observable/commit/a041b6d))
62 | * removed old tslint config ([e6530b2](https://github.com/Urigo/mongo-rxjs-observable/commit/e6530b2))
63 | * Replace 'meteor-typings' with '@types/meteor' ([b0d35e1](https://github.com/Urigo/mongo-rxjs-observable/commit/b0d35e1))
64 | * Update documentation for MeteorObservable ([c7816ba](https://github.com/Urigo/mongo-rxjs-observable/commit/c7816ba))
65 | * docs(MeteorObservable): Generated new docs ([0b56dd6](https://github.com/Urigo/mongo-rxjs-observable/commit/0b56dd6))
66 |
67 |
68 |
69 |
70 | ## 0.4.5 (2016-11-15)
71 |
72 | * chore(changelog): Minor fix ([49049a9](https://github.com/Urigo/mongo-rxjs-observable/commit/49049a9))
73 | * chore(changelog): updated changelog ([ec411b5](https://github.com/Urigo/mongo-rxjs-observable/commit/ec411b5))
74 | * chore(changelog): Updated changelog files ([025e825](https://github.com/Urigo/mongo-rxjs-observable/commit/025e825))
75 | * chore(compiler): fixed compiler version ([1d9cb43](https://github.com/Urigo/mongo-rxjs-observable/commit/1d9cb43))
76 | * chore(package): added greenkeeper config ([385c8c5](https://github.com/Urigo/mongo-rxjs-observable/commit/385c8c5))
77 | * chore(package): update @types/mocha to version 2.2.33 ([947f930](https://github.com/Urigo/mongo-rxjs-observable/commit/947f930))
78 | * chore(package): update typescript to version 2.0.9 ([05e2320](https://github.com/Urigo/mongo-rxjs-observable/commit/05e2320))
79 | * chore(README): Added npm version badge ([5e142cf](https://github.com/Urigo/mongo-rxjs-observable/commit/5e142cf))
80 | * chore(tests): added yarn lock file to tests app ([8edbe83](https://github.com/Urigo/mongo-rxjs-observable/commit/8edbe83))
81 | * chore(tests): fixes for missing package dependency ([572db5a](https://github.com/Urigo/mongo-rxjs-observable/commit/572db5a))
82 | * chore(tests): reverted yarn from tests app ([ab7da65](https://github.com/Urigo/mongo-rxjs-observable/commit/ab7da65))
83 | * chore(tests): updated tests application to use latest Meteor ([c3e40f6](https://github.com/Urigo/mongo-rxjs-observable/commit/c3e40f6))
84 | * chore(version): bump ([fbdddb9](https://github.com/Urigo/mongo-rxjs-observable/commit/fbdddb9))
85 | * chore(yarn): use yarn and added missing typings file ([ffdaa8f](https://github.com/Urigo/mongo-rxjs-observable/commit/ffdaa8f))
86 |
87 |
88 |
89 |
90 | ## 0.4.4 (2016-11-09)
91 |
92 | * chore(changelog): update CHANGELOG ([b3584de](https://github.com/Urigo/mongo-rxjs-observable/commit/b3584de))
93 | * chore(changelog): updated based on commits ([88e11a6](https://github.com/Urigo/mongo-rxjs-observable/commit/88e11a6))
94 | * chore(npmignore): Added npm ignore file ([b914e13](https://github.com/Urigo/mongo-rxjs-observable/commit/b914e13))
95 | * chore(package): update dependencies ([2296123](https://github.com/Urigo/mongo-rxjs-observable/commit/2296123))
96 |
97 |
98 |
99 |
100 | ## 0.4.3 (2016-11-03)
101 |
102 | * chore(changelog): Added auto generated changelog ([80dfa46](https://github.com/Urigo/mongo-rxjs-observable/commit/80dfa46))
103 | * chore(lint): Added bitHound badges ([7c034f1](https://github.com/Urigo/mongo-rxjs-observable/commit/7c034f1))
104 | * chore(lint): Added bitHound, Updated dependencies and lint issues ([36dfe7f](https://github.com/Urigo/mongo-rxjs-observable/commit/36dfe7f))
105 | * chore(package.json): bump version ([21ccc90](https://github.com/Urigo/mongo-rxjs-observable/commit/21ccc90))
106 | * chore(README): Updated badge ([efbd509](https://github.com/Urigo/mongo-rxjs-observable/commit/efbd509))
107 | * chore(release): bump ([c6f9bba](https://github.com/Urigo/mongo-rxjs-observable/commit/c6f9bba))
108 | * chore(scripts): Added build and clean before tests ([bd889de](https://github.com/Urigo/mongo-rxjs-observable/commit/bd889de))
109 | * chore(scripts): Added changelog script ([094b688](https://github.com/Urigo/mongo-rxjs-observable/commit/094b688))
110 | * chore(scripts): Removed typings script ([3060b1e](https://github.com/Urigo/mongo-rxjs-observable/commit/3060b1e))
111 | * chore(travis): Fixes for global modules ([0528ac0](https://github.com/Urigo/mongo-rxjs-observable/commit/0528ac0))
112 | * chore(typescript): Removed typings from travis script ([424001c](https://github.com/Urigo/mongo-rxjs-observable/commit/424001c))
113 | * chore(typescript): Replace typings with @types and fixed TS issues ([ae96888](https://github.com/Urigo/mongo-rxjs-observable/commit/ae96888))
114 | * bugfix(types): Fixes array type of Observable in find() ([7a3f0f5](https://github.com/Urigo/mongo-rxjs-observable/commit/7a3f0f5))
115 | * ci(README): Added ci badge to README ([bb2f480](https://github.com/Urigo/mongo-rxjs-observable/commit/bb2f480))
116 | * ci(travis): Added missing npm globals ([3c92baa](https://github.com/Urigo/mongo-rxjs-observable/commit/3c92baa))
117 | * ci(travis): Added missing npm install ([cad2a94](https://github.com/Urigo/mongo-rxjs-observable/commit/cad2a94))
118 | * ci(travis): Added missing package ([3802b70](https://github.com/Urigo/mongo-rxjs-observable/commit/3802b70))
119 | * ci(travis): Added pre test to the ci script ([5ba3396](https://github.com/Urigo/mongo-rxjs-observable/commit/5ba3396))
120 | * ci(travis): remove cache ([9b566ca](https://github.com/Urigo/mongo-rxjs-observable/commit/9b566ca))
121 | * ci(travis): Updated travis file ([a12f42d](https://github.com/Urigo/mongo-rxjs-observable/commit/a12f42d))
122 | * ci(travis): Updated travis file ([34dcc3e](https://github.com/Urigo/mongo-rxjs-observable/commit/34dcc3e))
123 | * docs(script): small fix ([02306d8](https://github.com/Urigo/mongo-rxjs-observable/commit/02306d8))
124 | * examples(angular2): Added angular2+meteor-ngrx with OnPush example ([9d97b51](https://github.com/Urigo/mongo-rxjs-observable/commit/9d97b51))
125 | * feat(multiple-subscribers): Applied another solution ([bc789db](https://github.com/Urigo/mongo-rxjs-observable/commit/bc789db))
126 | * feat(multiple-subscribers): Updated dist version and docs ([82b8a09](https://github.com/Urigo/mongo-rxjs-observable/commit/82b8a09))
127 | * feat(multiple-subscribers): Added publishReplay to the created Observable ([31f7698](https://github.com/Urigo/mongo-rxjs-observable/commit/31f7698))
128 |
129 |
130 |
131 |
132 | ## 0.4.1 (2016-11-01)
133 |
134 | * chore: bump rxjs dep ([de35ef9](https://github.com/Urigo/mongo-rxjs-observable/commit/de35ef9))
135 | * chore: ship NPM with ES6 modules and UMD bundle (which is referenced in package.json) ([afd95f1](https://github.com/Urigo/mongo-rxjs-observable/commit/afd95f1))
136 | * chore: tests, ts 2.0, types, ci ([e65fefa](https://github.com/Urigo/mongo-rxjs-observable/commit/e65fefa))
137 | * chore(bugfix): Added Tracker.autorun, and fixed issue with "subscribe" and the complete ([55dc88b](https://github.com/Urigo/mongo-rxjs-observable/commit/55dc88b))
138 | * chore(bugfix): Small fix in autorun ([106ffd4](https://github.com/Urigo/mongo-rxjs-observable/commit/106ffd4))
139 | * chore(collection): Added ability to wrap existing Mongo.Collection ([18c384f](https://github.com/Urigo/mongo-rxjs-observable/commit/18c384f))
140 | * chore(collection): Added ability to wrap existing Mongo.Collection ([d49e7bb](https://github.com/Urigo/mongo-rxjs-observable/commit/d49e7bb))
141 | * chore(collection): Changed the method name ([de33898](https://github.com/Urigo/mongo-rxjs-observable/commit/de33898))
142 | * chore(README): Added link to the API docs ([02d6f45](https://github.com/Urigo/mongo-rxjs-observable/commit/02d6f45))
143 | * chore(release): publish 0.2.3 ([17ed794](https://github.com/Urigo/mongo-rxjs-observable/commit/17ed794))
144 | * chore(release): publish 0.4.0 ([3b5bbf6](https://github.com/Urigo/mongo-rxjs-observable/commit/3b5bbf6))
145 | * chore(release): release 0.2.0 ([20f36f7](https://github.com/Urigo/mongo-rxjs-observable/commit/20f36f7))
146 | * chore(release): Release 0.3.0 ([68bc3b6](https://github.com/Urigo/mongo-rxjs-observable/commit/68bc3b6))
147 | * chore(tests): Added npm script for test and test:ci ([d275404](https://github.com/Urigo/mongo-rxjs-observable/commit/d275404))
148 | * chore(tests): Added unit tests for movedTo ([a254b96](https://github.com/Urigo/mongo-rxjs-observable/commit/a254b96))
149 | * chore(tests): Updated tests Meteor version to the latest ([703708f](https://github.com/Urigo/mongo-rxjs-observable/commit/703708f))
150 | * chore(tests): Updated tests scripts ([4beae33](https://github.com/Urigo/mongo-rxjs-observable/commit/4beae33))
151 | * chore(version): bump ([59772ff](https://github.com/Urigo/mongo-rxjs-observable/commit/59772ff))
152 | * feat: initial course code ([e163f52](https://github.com/Urigo/mongo-rxjs-observable/commit/e163f52))
153 | * feat: run subscriber callbacks in the current zone, i.e. zone operator can use most outer zone propa ([ec08c91](https://github.com/Urigo/mongo-rxjs-observable/commit/ec08c91))
154 | * feat(count): Added collectionCount Observable and it's tests ([4b027c6](https://github.com/Urigo/mongo-rxjs-observable/commit/4b027c6))
155 | * feat(jsdoc): Added documentation and build version, and docs generation script ([00e546a](https://github.com/Urigo/mongo-rxjs-observable/commit/00e546a))
156 | * feat(jsdoc): document MeteorObservable class ([c63917d](https://github.com/Urigo/mongo-rxjs-observable/commit/c63917d))
157 | * feat(jsdoc): Document ObservableCollection and ObservableCursor ([4b7391a](https://github.com/Urigo/mongo-rxjs-observable/commit/4b7391a))
158 | * feat(jsdoc): Fixed a typo ([50deb25](https://github.com/Urigo/mongo-rxjs-observable/commit/50deb25))
159 | * feat(jsdoc): Minor fixes for docs generation scripts ([ec051df](https://github.com/Urigo/mongo-rxjs-observable/commit/ec051df))
160 | * feat(jsdoc): Updated docs generation scripts and updated docs ([ded2eff](https://github.com/Urigo/mongo-rxjs-observable/commit/ded2eff))
161 | * feat(jsdoc): Updated documentation ([32413d2](https://github.com/Urigo/mongo-rxjs-observable/commit/32413d2))
162 | * bugfix(moved-to): Added missing callback and handler for moving items inside a collection ([e79af51](https://github.com/Urigo/mongo-rxjs-observable/commit/e79af51))
163 | * bugfix(multiple-subscribers): Attempt to fix the multiple subscribers issue ([ace9c78](https://github.com/Urigo/mongo-rxjs-observable/commit/ace9c78))
164 | * bugfix(multiple-subscribers): Revert :( ([f65a5e4](https://github.com/Urigo/mongo-rxjs-observable/commit/f65a5e4))
165 | * docs: correct readme ([58d9b8f](https://github.com/Urigo/mongo-rxjs-observable/commit/58d9b8f))
166 | * docs: readme ([24dc190](https://github.com/Urigo/mongo-rxjs-observable/commit/24dc190))
167 | * docs: readme ([2830da3](https://github.com/Urigo/mongo-rxjs-observable/commit/2830da3))
168 | * docs: readme ([a7ba861](https://github.com/Urigo/mongo-rxjs-observable/commit/a7ba861))
169 | * docs: readme ([d91c202](https://github.com/Urigo/mongo-rxjs-observable/commit/d91c202))
170 | * docs: readme ([6dda077](https://github.com/Urigo/mongo-rxjs-observable/commit/6dda077))
171 | * docs: readme ([1a7d6d2](https://github.com/Urigo/mongo-rxjs-observable/commit/1a7d6d2))
172 | * docs: readme ([7b43e16](https://github.com/Urigo/mongo-rxjs-observable/commit/7b43e16))
173 | * fix: #14 ([21b1a39](https://github.com/Urigo/mongo-rxjs-observable/commit/21b1a39))
174 | * .gitignore, useful. ([db1fe79](https://github.com/Urigo/mongo-rxjs-observable/commit/db1fe79))
175 | * Add complete() support to zone operator ([dc05322](https://github.com/Urigo/mongo-rxjs-observable/commit/dc05322))
176 | * Correctly reference the typings in package.json to enable imports. ([c836860](https://github.com/Urigo/mongo-rxjs-observable/commit/c836860))
177 | * Fix devDep of rxjs - use beta.12 ([801b134](https://github.com/Urigo/mongo-rxjs-observable/commit/801b134))
178 | * Fixed typo. ([5c7c3a5](https://github.com/Urigo/mongo-rxjs-observable/commit/5c7c3a5))
179 | * refactor: rename package to meteor-rxjs ([aff3619](https://github.com/Urigo/mongo-rxjs-observable/commit/aff3619))
180 |
181 |
182 |
183 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Uri Goldshtein
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Meteor + RxJS
2 |
3 | [](https://badge.fury.io/js/meteor-rxjs) [](https://travis-ci.org/Urigo/meteor-rxjs) [](https://www.bithound.io/github/Urigo/meteor-rxjs) [](https://www.bithound.io/github/Urigo/meteor-rxjs) [](https://www.bithound.io/github/Urigo/meteor-rxjs/master/dependencies/npm)
4 |
5 | Harness Meteor reactivity with RxJS.
6 |
7 | RxJS is built to simplify complexity dealing with reactive data flows. At the same time, Meteor's Minimongo cursors are a good target for RxJS API due to their reactivity. Thus, combining RxJS and Meteor, we bring together best parts of two worlds.
8 |
9 | # API Documentation
10 |
11 | API documentation is available inside this repository, [here](https://github.com/Urigo/meteor-rxjs/tree/master/docs).
12 |
13 | ## Mongo Cursor Observable
14 | As soon as you install this package (`npm install meteor-rxjs`), you have ability to use a special Mongo collection class that works
15 | with cursor observables instead of the ordinary Mongo cursors. In other words, one can subscribe on the Mongo cursor's data updates now as follows:
16 |
17 | ```ts
18 |
19 | import {MongoObservable} from 'meteor-rxjs';
20 |
21 | const Tasks = new MongoObservable.Collection('tasks');
22 |
23 | Tasks.find({checked: false})
24 | .map(tasks => tasks.length)
25 | .subscribe(todoCount => console.log(todoCount));
26 |
27 | ```
28 |
29 | Since this cursor observable is of RxJS’s type, every other methods and operators available to the observables as part of the RxJS API are also now available to the users, e.g., one can debounce data updates using RxJS’s debouncing operator:
30 |
31 | ```ts
32 |
33 | import {Observable} from 'rxjs';
34 |
35 | import {debounce, map} from 'rxjs/operators';
36 |
37 | Tasks.find({checked: false})
38 | .pipe(debounce(() => Observable.interval(50)))
39 | .pipe(map(tasks => tasks.length))
40 | .subscribe(todoCount => console.log(todoCount));
41 |
42 | ```
43 |
44 | ## Usage with Meteor packages
45 |
46 | Meteor has a lot of packages that extend `Mongo.Collection` with new methods. Since `MongoObservable.Collection` is a wrapper over `Mongo.Collection`, you can't use new methods on observable instances directly. The solution here is to pass `Mongo.Collection`'s instance to the observable constructor, and use them whenever you need after separately:
47 | ```ts
48 | let collection = new Mongo.Collection('foo');
49 | let observable = new MongoObservable.Collection(collection);
50 | collection.attachSchema(...); // with SimpleSchema package
51 | ```
52 |
53 | ## Usage in Angular
54 |
55 | Angular has tight integration with RxJS since Angular is desinged to support reactive UI updates.
56 | One of the realizations of this integration is `AsyncPipe`, which is supposed to be used with RxJS observables.
57 |
58 | In order to subscribe on the Mongo cursor observable's updates and iterate through the returned list of docs in Angular, one can use `AsyncPipe` in an Angular component as follows:
59 |
60 | ```ts
61 | import { MongoObservable, zoneOperator } from 'rxjs';
62 |
63 | const Tasks = new MongoObservable.Collection('tasks');
64 |
65 | @Component({
66 | selector: 'task-list',
67 | template: ``
68 | })
69 | class Tasks {
70 | tasks = Tasks.find().pipe(zoneOperator());
71 | }
72 |
73 | ````
74 |
75 | ### Zone operator
76 |
77 | As you can see above we called `zoneOperator` operator of the cursor observable. This is a special
78 | Zone operator that is implemeted by `meteor-rxjs` for the Angular users' convenience.
79 | This operator runs ngZone each time when new data arrives to the Mongo cursor observable,
80 | thus we force UI updates at the right time using it.
81 |
82 | It makes sense to improve performance of the above `Tasks` component by debouncing UI updates.
83 | In this case we are using Zone operator as well:
84 |
85 | ```ts
86 |
87 | class List {
88 | tasks = Tasks.find()
89 | .pipe(zoneOperator())
90 | .pipe(debounce(() => Observable.interval(50)))
91 | .zone();
92 | }
93 |
94 | ```
95 |
96 | ##License
97 | MIT
98 |
--------------------------------------------------------------------------------
/dist/MeteorObservable.d.ts:
--------------------------------------------------------------------------------
1 | import { Observable } from 'rxjs';
2 | /**
3 | * This is a class with static methods that wrap Meteor's API and return RxJS
4 | * Observables. The methods' signatures are the same as Meteor's, with the ]
5 | * exception that the callbacks are handled by Meteor-rxjs. Instead of
6 | * providing callbacks, you need to subscribe to the observables that are
7 | * returned. The methods that are wrapped in MeteorObservable are
8 | * [Meteor.call](https://docs.meteor.com/api/methods.html#Meteor-call),
9 | * [Meteor.autorun](https://docs.meteor.com/api/tracker.html#Tracker-autorun)
10 | * and [Meteor.subscribe](https://docs.meteor.com/api/pubsub.html#Meteor-subscribe).
11 | */
12 | export declare class MeteorObservable {
13 | /**
14 | * Invokes a [Meteor Method](https://docs.meteor.com/api/methods.html)
15 | * defined on the server, passing any number of arguments. This method has
16 | * the same signature as
17 | * [Meteor.call](https://docs.meteor.com/api/methods.html#Meteor-call), only
18 | * without the callbacks:
19 | * MeteorObservable.call(name, [...args])
20 | *
21 | *
22 | * @param {string} name - Name of the method in the Meteor server
23 | * @param {any} args - Parameters that will be forwarded to the method.
24 | * after the func call to initiate change detection.
25 | * @returns {Observable} - RxJS Observable, which completes when the
26 | * server returns a response.
27 | *
28 | * @example Example using Angular2 Component
29 | * class MyComponent {
30 | * constructor() {
31 | *
32 | * }
33 | *
34 | * doAction(payload) {
35 | * MeteorObservable.call("myData", payload).subscribe((response) => {
36 | * // Handle success and response from server!
37 | * }, (err) => {
38 | * // Handle error
39 | * });
40 | * }
41 | * }
42 | */
43 | static call(name: string, ...args: any[]): Observable;
44 | /**
45 | * When you subscribe to a collection, it tells the server to send records to
46 | * the client. This method has the same signature as
47 | * [Meteor.subscribe](https://docs.meteor.com/api/pubsub.html#Meteor-subscribe),
48 | * except without the callbacks again:
49 | * subscribe(name, [...args])
50 | *
51 | * You can use this method from any Angular2 element - such as Component,
52 | * Pipe or Service.
53 | *
54 | * @param {string} name - Name of the publication in the Meteor server
55 | * @param {any} args - Parameters that will be forwarded to the publication.
56 | * after the func call to initiate change detection.
57 | * @returns {Observable} - RxJS Observable, which completes when the
58 | * subscription is ready.
59 | *
60 | * @example Example using Angular2 Service
61 | * class MyService {
62 | * private meteorSubscription: Observable;
63 | *
64 | * constructor() {
65 | *
66 | * }
67 | *
68 | * subscribeToData() {
69 | * this.meteorSubscription = MeteorObservable.subscribe("myData").subscribe(() => {
70 | * // Subscription is ready!
71 | * });
72 | * }
73 | *
74 | * unsubscribeToData() {
75 | * this.meteorSubscription.unsubscribe();
76 | * }
77 | * }
78 | *
79 | * @example Example using Angular2 Component
80 | * class MyComponent implements OnInit, OnDestroy {
81 | * private meteorSubscription: Observable;
82 | *
83 | * constructor() {
84 | *
85 | * }
86 | *
87 | * ngOnInit() {
88 | * this.meteorSubscription = MeteorObservable.subscribe("myData").subscribe(() => {
89 | * // Subscription is ready!
90 | * });
91 | * }
92 | *
93 | * ngOnDestroy() {
94 | * this.meteorSubscription.unsubscribe();
95 | * }
96 | * }
97 | *
98 | * @see {@link http://docs.meteor.com/api/pubsub.html|Publications in Meteor documentation}
99 | */
100 | static subscribe(name: string, ...args: any[]): Observable;
101 | /**
102 | * Allows you to run a function every time there is a change is a reactive
103 | * data sources. This method has the same signature as
104 | * [Meteor.autorun](https://docs.meteor.com/api/tracker.html#Tracker-autorun),
105 | * only without the callback:
106 | * MeteorObservable.autorun()
107 | *
108 | * @returns {Observable} - RxJS Observable, which trigger the subscription callback
109 | * each time that Meteor Tracker detects a change.
110 | * @example Example using Angular2 Component
111 | * class MyComponent {
112 | * constructor() {
113 | *
114 | * }
115 | *
116 | * doAction(payload) {
117 | * MeteorObservable.autorun().subscribe(() => {
118 | * // Handle Tracker autorun change
119 | * });
120 | * }
121 | * }
122 | */
123 | static autorun(): Observable;
124 | }
125 |
--------------------------------------------------------------------------------
/dist/MeteorObservable.js:
--------------------------------------------------------------------------------
1 | import { Observable } from 'rxjs';
2 | import { isMeteorCallbacks, forkZone, removeObserver } from './utils';
3 | var liveSubscriptions = [];
4 | function throwInvalidCallback(method) {
5 | throw new Error("Invalid " + method + " arguments:\n your last param can't be a callback function,\n please remove it and use \".subscribe\" of the Observable!");
6 | }
7 | /**
8 | * This is a class with static methods that wrap Meteor's API and return RxJS
9 | * Observables. The methods' signatures are the same as Meteor's, with the ]
10 | * exception that the callbacks are handled by Meteor-rxjs. Instead of
11 | * providing callbacks, you need to subscribe to the observables that are
12 | * returned. The methods that are wrapped in MeteorObservable are
13 | * [Meteor.call](https://docs.meteor.com/api/methods.html#Meteor-call),
14 | * [Meteor.autorun](https://docs.meteor.com/api/tracker.html#Tracker-autorun)
15 | * and [Meteor.subscribe](https://docs.meteor.com/api/pubsub.html#Meteor-subscribe).
16 | */
17 | var MeteorObservable = /** @class */ (function () {
18 | function MeteorObservable() {
19 | }
20 | /**
21 | * Invokes a [Meteor Method](https://docs.meteor.com/api/methods.html)
22 | * defined on the server, passing any number of arguments. This method has
23 | * the same signature as
24 | * [Meteor.call](https://docs.meteor.com/api/methods.html#Meteor-call), only
25 | * without the callbacks:
26 | * MeteorObservable.call(name, [...args])
27 | *
28 | *
29 | * @param {string} name - Name of the method in the Meteor server
30 | * @param {any} args - Parameters that will be forwarded to the method.
31 | * after the func call to initiate change detection.
32 | * @returns {Observable} - RxJS Observable, which completes when the
33 | * server returns a response.
34 | *
35 | * @example Example using Angular2 Component
36 | * class MyComponent {
37 | * constructor() {
38 | *
39 | * }
40 | *
41 | * doAction(payload) {
42 | * MeteorObservable.call("myData", payload).subscribe((response) => {
43 | * // Handle success and response from server!
44 | * }, (err) => {
45 | * // Handle error
46 | * });
47 | * }
48 | * }
49 | */
50 | MeteorObservable.call = function (name) {
51 | var args = [];
52 | for (var _i = 1; _i < arguments.length; _i++) {
53 | args[_i - 1] = arguments[_i];
54 | }
55 | var lastParam = args[args.length - 1];
56 | if (isMeteorCallbacks(lastParam)) {
57 | throwInvalidCallback('MeteorObservable.call');
58 | }
59 | var zone = forkZone();
60 | return Observable.create(function (observer) {
61 | Meteor.call.apply(Meteor, [name].concat(args.concat([
62 | function (error, result) {
63 | zone.run(function () {
64 | error ? observer.error(error) :
65 | observer.next(result);
66 | observer.complete();
67 | });
68 | }
69 | ])));
70 | });
71 | };
72 | /**
73 | * When you subscribe to a collection, it tells the server to send records to
74 | * the client. This method has the same signature as
75 | * [Meteor.subscribe](https://docs.meteor.com/api/pubsub.html#Meteor-subscribe),
76 | * except without the callbacks again:
77 | * subscribe(name, [...args])
78 | *
79 | * You can use this method from any Angular2 element - such as Component,
80 | * Pipe or Service.
81 | *
82 | * @param {string} name - Name of the publication in the Meteor server
83 | * @param {any} args - Parameters that will be forwarded to the publication.
84 | * after the func call to initiate change detection.
85 | * @returns {Observable} - RxJS Observable, which completes when the
86 | * subscription is ready.
87 | *
88 | * @example Example using Angular2 Service
89 | * class MyService {
90 | * private meteorSubscription: Observable;
91 | *
92 | * constructor() {
93 | *
94 | * }
95 | *
96 | * subscribeToData() {
97 | * this.meteorSubscription = MeteorObservable.subscribe("myData").subscribe(() => {
98 | * // Subscription is ready!
99 | * });
100 | * }
101 | *
102 | * unsubscribeToData() {
103 | * this.meteorSubscription.unsubscribe();
104 | * }
105 | * }
106 | *
107 | * @example Example using Angular2 Component
108 | * class MyComponent implements OnInit, OnDestroy {
109 | * private meteorSubscription: Observable;
110 | *
111 | * constructor() {
112 | *
113 | * }
114 | *
115 | * ngOnInit() {
116 | * this.meteorSubscription = MeteorObservable.subscribe("myData").subscribe(() => {
117 | * // Subscription is ready!
118 | * });
119 | * }
120 | *
121 | * ngOnDestroy() {
122 | * this.meteorSubscription.unsubscribe();
123 | * }
124 | * }
125 | *
126 | * @see {@link http://docs.meteor.com/api/pubsub.html|Publications in Meteor documentation}
127 | */
128 | MeteorObservable.subscribe = function (name) {
129 | var args = [];
130 | for (var _i = 1; _i < arguments.length; _i++) {
131 | args[_i - 1] = arguments[_i];
132 | }
133 | var lastParam = args[args.length - 1];
134 | if (isMeteorCallbacks(lastParam)) {
135 | throwInvalidCallback('MeteorObservable.subscribe');
136 | }
137 | var zone = forkZone();
138 | var observers = [];
139 | var subscribe = function () {
140 | return Meteor.subscribe.apply(Meteor, [name].concat(args.concat([{
141 | onError: function (error) {
142 | zone.run(function () {
143 | observers.forEach(function (observer) { return observer.error(error); });
144 | });
145 | },
146 | onReady: function () {
147 | zone.run(function () {
148 | observers.forEach(function (observer) { return observer.next(); });
149 | });
150 | }
151 | }
152 | ])));
153 | };
154 | var subHandler = null;
155 | return Observable.create(function (observer) {
156 | observers.push(observer);
157 | // Execute subscribe lazily.
158 | if (subHandler === null) {
159 | subHandler = subscribe();
160 | if (liveSubscriptions.find(function (sub) { return sub === subHandler.subscriptionId; })) {
161 | // subscription already exists, call observer.next() since Meteor won't.
162 | observer.next();
163 | }
164 | else {
165 | liveSubscriptions.push(subHandler.subscriptionId);
166 | }
167 | }
168 | return function () {
169 | removeObserver(observers, observer, function () {
170 | // remove subscription from liveSubscriptions list
171 | var i = liveSubscriptions.findIndex(function (sub) { return sub === subHandler.subscriptionId; });
172 | if (i > -1) {
173 | liveSubscriptions.splice(i, 1);
174 | }
175 | subHandler.stop();
176 | });
177 | };
178 | });
179 | };
180 | /**
181 | * Allows you to run a function every time there is a change is a reactive
182 | * data sources. This method has the same signature as
183 | * [Meteor.autorun](https://docs.meteor.com/api/tracker.html#Tracker-autorun),
184 | * only without the callback:
185 | * MeteorObservable.autorun()
186 | *
187 | * @returns {Observable} - RxJS Observable, which trigger the subscription callback
188 | * each time that Meteor Tracker detects a change.
189 | * @example Example using Angular2 Component
190 | * class MyComponent {
191 | * constructor() {
192 | *
193 | * }
194 | *
195 | * doAction(payload) {
196 | * MeteorObservable.autorun().subscribe(() => {
197 | * // Handle Tracker autorun change
198 | * });
199 | * }
200 | * }
201 | */
202 | MeteorObservable.autorun = function () {
203 | var zone = forkZone();
204 | var observers = [];
205 | var autorun = function () {
206 | return Tracker.autorun(function (computation) {
207 | zone.run(function () {
208 | observers.forEach(function (observer) { return observer.next(computation); });
209 | });
210 | });
211 | };
212 | var handler = null;
213 | return Observable.create(function (observer) {
214 | observers.push(observer);
215 | // Execute autorun lazily.
216 | if (handler === null) {
217 | handler = autorun();
218 | }
219 | return function () {
220 | removeObserver(observers, observer, function () { return handler.stop(); });
221 | };
222 | });
223 | };
224 | return MeteorObservable;
225 | }());
226 | export { MeteorObservable };
227 | //# sourceMappingURL=MeteorObservable.js.map
--------------------------------------------------------------------------------
/dist/MeteorObservable.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"MeteorObservable.js","sourceRoot":"","sources":["../src/MeteorObservable.ts"],"names":[],"mappings":"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"}
--------------------------------------------------------------------------------
/dist/ObservableCollection.d.ts:
--------------------------------------------------------------------------------
1 | import { Observable } from 'rxjs';
2 | import { ObservableCursor } from './ObservableCursor';
3 | import Selector = Mongo.Selector;
4 | import ObjectID = Mongo.ObjectID;
5 | import SortSpecifier = Mongo.SortSpecifier;
6 | import FieldSpecifier = Mongo.FieldSpecifier;
7 | import Modifier = Mongo.Modifier;
8 | export declare module MongoObservable {
9 | interface ConstructorOptions {
10 | connection?: Object;
11 | idGeneration?: string;
12 | transform?: Function;
13 | }
14 | interface AllowDenyOptionsObject {
15 | insert?: (userId: string, doc: T) => boolean;
16 | update?: (userId: string, doc: T, fieldNames: string[], modifier: any) => boolean;
17 | remove?: (userId: string, doc: T) => boolean;
18 | fetch?: string[];
19 | transform?: Function;
20 | }
21 | /**
22 | * Creates a new MongoObservable.Collection from an existing of predefined Mongo.Collection.
23 | * Use this feature to wrap existing collections such as Meteor.users.
24 | * @param {Mongo.Collection} collection - The collection.
25 | * @returns {MongoObservable.Collection} - Wrapped collection.
26 | * @static
27 | */
28 | function fromExisting(collection: Mongo.Collection): MongoObservable.Collection;
29 | /**
30 | * A class represents a MongoDB collection in the client side, wrapped with RxJS
31 | * Observables, so you can use it with your Angular 2 easier.
32 | * The wrapper has the same API as Mongo.Collection, only the "find" method returns
33 | * an ObservableCursor instead of regular Mongo.Cursor.
34 | *
35 | * T is a generic type - should be used with the type of the objects inside the collection.
36 | */
37 | class Collection {
38 | private _collection;
39 | /**
40 | * Creates a new Mongo.Collection instance wrapped with Observable features.
41 | * @param {String | Mongo.Collection} nameOrExisting - The name of the collection. If null, creates an
42 | * unmanaged (unsynchronized) local collection. If provided an instance of existing collection, will
43 | * create a wrapper for the existing Mongo.Collection.
44 | * @param {ConstructorOptions} options - Creation options.
45 | * @constructor
46 | */
47 | constructor(nameOrExisting: string | Mongo.Collection, options?: ConstructorOptions);
48 | /**
49 | * Returns the Mongo.Collection object that wrapped with the MongoObservable.Collection.
50 | * @returns {Mongo.Collection} The Collection instance
51 | */
52 | readonly collection: Mongo.Collection;
53 | /**
54 | * Allow users to write directly to this collection from client code, subject to limitations you define.
55 | *
56 | * @returns {Boolean}
57 | */
58 | allow(options: AllowDenyOptionsObject): boolean;
59 | /**
60 | * Override allow rules.
61 | *
62 | * @returns {Boolean}
63 | */
64 | deny(options: AllowDenyOptionsObject): boolean;
65 | /**
66 | * Returns the Collection object corresponding to this collection from the npm
67 | * mongodb driver module which is wrapped by Mongo.Collection.
68 | *
69 | * @returns {Mongo.Collection} The Collection instance
70 | *
71 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-rawCollection|rawCollection on Meteor documentation}
72 | */
73 | rawCollection(): any;
74 | /**
75 | * Returns the Db object corresponding to this collection's database connection from the
76 | * npm mongodb driver module which is wrapped by Mongo.Collection.
77 | *
78 | * @returns {Mongo.Db} The Db instance
79 | *
80 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-rawDatabase|rawDatabase on Meteor documentation}
81 | */
82 | rawDatabase(): any;
83 | /**
84 | * Insert a document in the collection.
85 | *
86 | * @param {T} doc - The document to insert. May not yet have an _id
87 | * attribute, in which case Meteor will generate one for you.
88 | * @returns {Observable} Observable which completes with the inserted ObjectId
89 | *
90 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-insert|insert on Meteor documentation}
91 | */
92 | insert(doc: T): Observable;
93 | /**
94 | * Remove documents from the collection.
95 | *
96 | * @param {Collection~MongoQuerySelector} selector - Specifies which documents to modify
97 | * @returns {Observable} Observable which completes with the number of affected rows
98 | *
99 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-remove|remove on Meteor documentation}
100 | */
101 | remove(selector: Selector | ObjectID | string): Observable;
102 | /**
103 | * Modify one or more documents in the collection.
104 | *
105 | * @param {Collection~MongoQuerySelector} selector - Specifies which documents to modify
106 | * @param {Modifier} modifier - Specifies how to modify the documents
107 | * @param {MongoUpdateOptions} options - Update options
108 | * first argument and, if no error, the number of affected documents as the second
109 | * @returns {Observable} Observable which completes with the number of affected rows
110 | *
111 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-update|update on Meteor documentation}
112 | */
113 | update(selector: Selector | ObjectID | string, modifier: Modifier, options?: {
114 | multi?: boolean;
115 | upsert?: boolean;
116 | }): Observable;
117 | /**
118 | * Finds the first document that matches the selector, as ordered by sort and skip options.
119 | *
120 | * @param {Collection~MongoQuerySelector} selector - Specifies which documents to modify
121 | * @param {Modifier} modifier - Specifies how to modify the documents
122 | * @param {MongoUpsertOptions} options - Upsert options
123 | * first argument and, if no error, the number of affected documents as the second.
124 | * @returns {Observable<{numberAffected, insertedId}>} Observable which completes with an
125 | * Object that contain the keys numberAffected and insertedId.
126 | *
127 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-upsert|upsert on Meteor documentation}
128 | */
129 | upsert(selector: Selector | ObjectID | string, modifier: Modifier, options?: {
130 | multi?: boolean;
131 | }): Observable;
132 | /**
133 | * Method has the same notation as Mongo.Collection.find, only returns Observable.
134 | *
135 | * @param {Collection~MongoQuerySelector} selector - A query describing the documents to find
136 | * @param {Collection~MongoQueryOptions} options - Query options, such as sort, limit, etc.
137 | * @returns {ObservableCursor} RxJS Observable wrapped with Meteor features.
138 | * @example Using Angular2 Component
139 | * const MyCollection = MongoObservable.Collection("myCollection");
140 | *
141 | * class MyComponent {
142 | * private myData: ObservableCursor;
143 | *
144 | * constructor() {
145 | * this.myData = MyCollection.find({}, {limit: 10});
146 | * }
147 | * }
148 | *
149 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-find|find on Meteor documentation}
150 | */
151 | find(selector?: Selector | ObjectID | string, options?: {
152 | sort?: SortSpecifier;
153 | skip?: number;
154 | limit?: number;
155 | fields?: FieldSpecifier;
156 | reactive?: boolean;
157 | transform?: Function;
158 | }): ObservableCursor;
159 | /**
160 | * Finds the first document that matches the selector, as ordered by sort and skip options.
161 | *
162 | * @param {Collection~MongoQuerySelector} selector - A query describing the documents to find
163 | * @param {Collection~MongoQueryOptions} options - Query options, such as sort, limit, etc.
164 | * @returns {any} The first object, or `undefined` in case of non-existing object.
165 | *
166 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-findOne|findOne on Meteor documentation}
167 | */
168 | findOne(selector?: Selector | ObjectID | string, options?: {
169 | sort?: SortSpecifier;
170 | skip?: number;
171 | fields?: FieldSpecifier;
172 | reactive?: boolean;
173 | transform?: Function;
174 | }): T;
175 | private _createObservable(observers);
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/dist/ObservableCollection.js:
--------------------------------------------------------------------------------
1 | import { Observable } from 'rxjs';
2 | import { ObservableCursor } from './ObservableCursor';
3 | import { removeObserver } from './utils';
4 | export var MongoObservable;
5 | (function (MongoObservable) {
6 | 'use strict';
7 | /**
8 | * Creates a new MongoObservable.Collection from an existing of predefined Mongo.Collection.
9 | * Use this feature to wrap existing collections such as Meteor.users.
10 | * @param {Mongo.Collection} collection - The collection.
11 | * @returns {MongoObservable.Collection} - Wrapped collection.
12 | * @static
13 | */
14 | function fromExisting(collection) {
15 | return new MongoObservable.Collection(collection);
16 | }
17 | MongoObservable.fromExisting = fromExisting;
18 | /**
19 | * A class represents a MongoDB collection in the client side, wrapped with RxJS
20 | * Observables, so you can use it with your Angular 2 easier.
21 | * The wrapper has the same API as Mongo.Collection, only the "find" method returns
22 | * an ObservableCursor instead of regular Mongo.Cursor.
23 | *
24 | * T is a generic type - should be used with the type of the objects inside the collection.
25 | */
26 | var Collection = /** @class */ (function () {
27 | /**
28 | * Creates a new Mongo.Collection instance wrapped with Observable features.
29 | * @param {String | Mongo.Collection} nameOrExisting - The name of the collection. If null, creates an
30 | * unmanaged (unsynchronized) local collection. If provided an instance of existing collection, will
31 | * create a wrapper for the existing Mongo.Collection.
32 | * @param {ConstructorOptions} options - Creation options.
33 | * @constructor
34 | */
35 | function Collection(nameOrExisting, options) {
36 | if (nameOrExisting instanceof Mongo.Collection) {
37 | this._collection = nameOrExisting;
38 | }
39 | else {
40 | this._collection = new Mongo.Collection(nameOrExisting, options);
41 | }
42 | }
43 | Object.defineProperty(Collection.prototype, "collection", {
44 | /**
45 | * Returns the Mongo.Collection object that wrapped with the MongoObservable.Collection.
46 | * @returns {Mongo.Collection} The Collection instance
47 | */
48 | get: function () {
49 | return this._collection;
50 | },
51 | enumerable: true,
52 | configurable: true
53 | });
54 | /**
55 | * Allow users to write directly to this collection from client code, subject to limitations you define.
56 | *
57 | * @returns {Boolean}
58 | */
59 | Collection.prototype.allow = function (options) {
60 | return this._collection.allow(options);
61 | };
62 | /**
63 | * Override allow rules.
64 | *
65 | * @returns {Boolean}
66 | */
67 | Collection.prototype.deny = function (options) {
68 | return this._collection.deny(options);
69 | };
70 | /**
71 | * Returns the Collection object corresponding to this collection from the npm
72 | * mongodb driver module which is wrapped by Mongo.Collection.
73 | *
74 | * @returns {Mongo.Collection} The Collection instance
75 | *
76 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-rawCollection|rawCollection on Meteor documentation}
77 | */
78 | Collection.prototype.rawCollection = function () {
79 | return this._collection.rawCollection();
80 | };
81 | /**
82 | * Returns the Db object corresponding to this collection's database connection from the
83 | * npm mongodb driver module which is wrapped by Mongo.Collection.
84 | *
85 | * @returns {Mongo.Db} The Db instance
86 | *
87 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-rawDatabase|rawDatabase on Meteor documentation}
88 | */
89 | Collection.prototype.rawDatabase = function () {
90 | return this._collection.rawDatabase();
91 | };
92 | /**
93 | * Insert a document in the collection.
94 | *
95 | * @param {T} doc - The document to insert. May not yet have an _id
96 | * attribute, in which case Meteor will generate one for you.
97 | * @returns {Observable} Observable which completes with the inserted ObjectId
98 | *
99 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-insert|insert on Meteor documentation}
100 | */
101 | Collection.prototype.insert = function (doc) {
102 | var observers = [];
103 | var obs = this._createObservable(observers);
104 | this._collection.insert(doc, function (error, docId) {
105 | observers.forEach(function (observer) {
106 | error ? observer.error(error) :
107 | observer.next(docId);
108 | observer.complete();
109 | });
110 | });
111 | return obs;
112 | };
113 | /**
114 | * Remove documents from the collection.
115 | *
116 | * @param {Collection~MongoQuerySelector} selector - Specifies which documents to modify
117 | * @returns {Observable} Observable which completes with the number of affected rows
118 | *
119 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-remove|remove on Meteor documentation}
120 | */
121 | Collection.prototype.remove = function (selector) {
122 | var observers = [];
123 | var obs = this._createObservable(observers);
124 | this._collection.remove(selector, function (error, removed) {
125 | observers.forEach(function (observer) {
126 | error ? observer.error(error) :
127 | observer.next(removed);
128 | observer.complete();
129 | });
130 | });
131 | return obs;
132 | };
133 | /**
134 | * Modify one or more documents in the collection.
135 | *
136 | * @param {Collection~MongoQuerySelector} selector - Specifies which documents to modify
137 | * @param {Modifier} modifier - Specifies how to modify the documents
138 | * @param {MongoUpdateOptions} options - Update options
139 | * first argument and, if no error, the number of affected documents as the second
140 | * @returns {Observable} Observable which completes with the number of affected rows
141 | *
142 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-update|update on Meteor documentation}
143 | */
144 | Collection.prototype.update = function (selector, modifier, options) {
145 | var observers = [];
146 | var obs = this._createObservable(observers);
147 | this._collection.update(selector, modifier, options, function (error, updated) {
148 | observers.forEach(function (observer) {
149 | error ? observer.error(error) :
150 | observer.next(updated);
151 | observer.complete();
152 | });
153 | });
154 | return obs;
155 | };
156 | /**
157 | * Finds the first document that matches the selector, as ordered by sort and skip options.
158 | *
159 | * @param {Collection~MongoQuerySelector} selector - Specifies which documents to modify
160 | * @param {Modifier} modifier - Specifies how to modify the documents
161 | * @param {MongoUpsertOptions} options - Upsert options
162 | * first argument and, if no error, the number of affected documents as the second.
163 | * @returns {Observable<{numberAffected, insertedId}>} Observable which completes with an
164 | * Object that contain the keys numberAffected and insertedId.
165 | *
166 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-upsert|upsert on Meteor documentation}
167 | */
168 | Collection.prototype.upsert = function (selector, modifier, options) {
169 | var observers = [];
170 | var obs = this._createObservable(observers);
171 | this._collection.upsert(selector, modifier, options, function (error, affected) {
172 | observers.forEach(function (observer) {
173 | error ? observer.error(error) :
174 | observer.next(affected);
175 | observer.complete();
176 | });
177 | });
178 | return obs;
179 | };
180 | /**
181 | * Method has the same notation as Mongo.Collection.find, only returns Observable.
182 | *
183 | * @param {Collection~MongoQuerySelector} selector - A query describing the documents to find
184 | * @param {Collection~MongoQueryOptions} options - Query options, such as sort, limit, etc.
185 | * @returns {ObservableCursor} RxJS Observable wrapped with Meteor features.
186 | * @example Using Angular2 Component
187 | * const MyCollection = MongoObservable.Collection("myCollection");
188 | *
189 | * class MyComponent {
190 | * private myData: ObservableCursor;
191 | *
192 | * constructor() {
193 | * this.myData = MyCollection.find({}, {limit: 10});
194 | * }
195 | * }
196 | *
197 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-find|find on Meteor documentation}
198 | */
199 | Collection.prototype.find = function (selector, options) {
200 | var cursor = this._collection.find.apply(this._collection, arguments);
201 | return ObservableCursor.create(cursor);
202 | };
203 | /**
204 | * Finds the first document that matches the selector, as ordered by sort and skip options.
205 | *
206 | * @param {Collection~MongoQuerySelector} selector - A query describing the documents to find
207 | * @param {Collection~MongoQueryOptions} options - Query options, such as sort, limit, etc.
208 | * @returns {any} The first object, or `undefined` in case of non-existing object.
209 | *
210 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-findOne|findOne on Meteor documentation}
211 | */
212 | Collection.prototype.findOne = function (selector, options) {
213 | return this._collection.findOne.apply(this._collection, arguments);
214 | };
215 | Collection.prototype._createObservable = function (observers) {
216 | return Observable.create(function (observer) {
217 | observers.push(observer);
218 | return function () {
219 | removeObserver(observers, observer);
220 | };
221 | });
222 | };
223 | return Collection;
224 | }());
225 | MongoObservable.Collection = Collection;
226 | })(MongoObservable || (MongoObservable = {}));
227 | /**
228 | * An options object for MongoDB queries.
229 | * @typedef {Object} Collection~MongoQueryOptions
230 | * @property {Object} sort - Sort order (default: natural order)
231 | * @property {Number} skip - Number of results to skip at the beginning
232 | * @property {Object} fields - Dictionary of fields to return or exclude.
233 | * @property {Boolean} reactive - (Client only) Default true; pass false to disable reactivity
234 | * @property {Function} transform - Overrides transform on the Collection for this cursor. Pass null to disable transformation.
235 | */
236 | /**
237 | * A MongoDB query selector representation.
238 | * @typedef {(Mongo.Selector|Mongo.ObjectID|string)} Collection~MongoQuerySelector
239 | */
240 | /**
241 | * A MongoDB query options for upsert action
242 | * @typedef {Object} Collection~MongoUpsertOptions
243 | * @property {Boolean} multi - True to modify all matching documents;
244 | * false to only modify one of the matching documents (the default).
245 | */
246 | /**
247 | * A MongoDB query options for update action
248 | * @typedef {Object} Collection~MongoUpdateOptions
249 | * @property {Boolean} multi - True to modify all matching documents;
250 | * @property {Boolean} upsert - True to use upsert logic.
251 | */
252 | //# sourceMappingURL=ObservableCollection.js.map
--------------------------------------------------------------------------------
/dist/ObservableCollection.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"ObservableCollection.js","sourceRoot":"","sources":["../src/ObservableCollection.ts"],"names":[],"mappings":"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"}
--------------------------------------------------------------------------------
/dist/ObservableCursor.d.ts:
--------------------------------------------------------------------------------
1 | import { Observable } from 'rxjs';
2 | export declare class ObservableCursor extends Observable {
3 | private _zone;
4 | private _data;
5 | private _cursor;
6 | private _hCursor;
7 | private _observers;
8 | private _countObserver;
9 | private _isDataInitinialized;
10 | /**
11 | * Static method which creates an ObservableCursor from Mongo.Cursor.
12 | * Use this to create an ObservableCursor object from an existing Mongo.Cursor.
13 | * Prefer to create an Cursors from the ObservableCollection instance instead.
14 | *
15 | * @param {Mongo.Cursor} cursor - The Mongo.Cursor to wrap.
16 | * @static
17 | * @returns {ObservableCursor} Wrapped Cursor.
18 | */
19 | static create(cursor: Mongo.Cursor): ObservableCursor;
20 | /**
21 | * @constructor
22 | * @extends Observable
23 | * @param {Mongo.Cursor} cursor - The Mongo.Cursor to wrap.
24 | */
25 | constructor(cursor: Mongo.Cursor);
26 | /**
27 | * Returns the actual Mongo.Cursor that wrapped by current ObservableCursor instance.
28 | * @return {Mongo.Cursor} The actual MongoDB Cursor.
29 | */
30 | readonly cursor: Mongo.Cursor;
31 | /**
32 | * A wrapper for Mongo.Cursor.count() method - returns an Observable of number, which
33 | * triggers each time there is a change in the collection, and exposes the number of
34 | * objects in the collection.
35 | * @returns {Observable} Observable which trigger the callback when the
36 | * count of the object changes.
37 | */
38 | collectionCount(): Observable;
39 | /**
40 | * Stops the observation on the cursor.
41 | */
42 | stop(): void;
43 | /**
44 | * Clears the Observable definition.
45 | * Use this method only when the Observable is still cold, and there are no active subscriptions yet.
46 | */
47 | dispose(): void;
48 | /**
49 | * Return all matching documents as an Array.
50 | *
51 | * @return {Array} The array with the matching documents.
52 | */
53 | fetch(): Array;
54 | /**
55 | * Watch a query. Receive callbacks as the result set changes.
56 | * @param {Mongo.ObserveCallbacks} callbacks - The callbacks object.
57 | * @return {Meteor.LiveQueryHandle} The array with the matching documents.
58 | */
59 | observe(callbacks: Object): Meteor.LiveQueryHandle;
60 | /**
61 | * Watch a query. Receive callbacks as the result set changes.
62 | * Only the differences between the old and new documents are passed to the callbacks.
63 | * @param {Mongo.ObserveChangesCallbacks} callbacks - The callbacks object.
64 | * @return {Meteor.LiveQueryHandle} The array with the matching documents.
65 | */
66 | observeChanges(callbacks: Object): Meteor.LiveQueryHandle;
67 | _runComplete(): void;
68 | _runNext(data: Array): void;
69 | _addedAt(doc: any, at: any, before: any): void;
70 | _changedAt(doc: any, old: any, at: any): void;
71 | _removedAt(doc: any, at: any): void;
72 | _movedTo(doc: any, fromIndex: any, toIndex: any): void;
73 | _handleChange(): void;
74 | _observeCursor(cursor: Mongo.Cursor): any;
75 | }
76 |
--------------------------------------------------------------------------------
/dist/ObservableCursor.js:
--------------------------------------------------------------------------------
1 | var __extends = (this && this.__extends) || (function () {
2 | var extendStatics = Object.setPrototypeOf ||
3 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
4 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
5 | return function (d, b) {
6 | extendStatics(d, b);
7 | function __() { this.constructor = d; }
8 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
9 | };
10 | })();
11 | import { Observable, Subject } from 'rxjs';
12 | import { gZone, forkZone, removeObserver } from './utils';
13 | var ObservableCursor = /** @class */ (function (_super) {
14 | __extends(ObservableCursor, _super);
15 | /**
16 | * @constructor
17 | * @extends Observable
18 | * @param {Mongo.Cursor} cursor - The Mongo.Cursor to wrap.
19 | */
20 | function ObservableCursor(cursor) {
21 | var _this = _super.call(this, function (observer) {
22 | _this._observers.push(observer);
23 | if (!_this._hCursor) {
24 | _this._hCursor = _this._observeCursor(cursor);
25 | }
26 | Meteor.setTimeout(function () {
27 | if (_this._isDataInitinialized) {
28 | observer.next(_this._data);
29 | }
30 | else if (cursor.count() === 0) {
31 | _this._isDataInitinialized = true;
32 | observer.next(_this._data);
33 | }
34 | }, 0);
35 | return function () {
36 | removeObserver(_this._observers, observer, function () { return _this.stop(); });
37 | };
38 | }) || this;
39 | _this._data = [];
40 | _this._observers = [];
41 | _this._countObserver = new Subject();
42 | _this._isDataInitinialized = false;
43 | _.extend(_this, _.omit(cursor, 'count', 'map'));
44 | _this._cursor = cursor;
45 | _this._zone = forkZone();
46 | return _this;
47 | }
48 | /**
49 | * Static method which creates an ObservableCursor from Mongo.Cursor.
50 | * Use this to create an ObservableCursor object from an existing Mongo.Cursor.
51 | * Prefer to create an Cursors from the ObservableCollection instance instead.
52 | *
53 | * @param {Mongo.Cursor} cursor - The Mongo.Cursor to wrap.
54 | * @static
55 | * @returns {ObservableCursor} Wrapped Cursor.
56 | */
57 | ObservableCursor.create = function (cursor) {
58 | return new ObservableCursor(cursor);
59 | };
60 | Object.defineProperty(ObservableCursor.prototype, "cursor", {
61 | /**
62 | * Returns the actual Mongo.Cursor that wrapped by current ObservableCursor instance.
63 | * @return {Mongo.Cursor} The actual MongoDB Cursor.
64 | */
65 | get: function () {
66 | return this._cursor;
67 | },
68 | enumerable: true,
69 | configurable: true
70 | });
71 | /**
72 | * A wrapper for Mongo.Cursor.count() method - returns an Observable of number, which
73 | * triggers each time there is a change in the collection, and exposes the number of
74 | * objects in the collection.
75 | * @returns {Observable} Observable which trigger the callback when the
76 | * count of the object changes.
77 | */
78 | ObservableCursor.prototype.collectionCount = function () {
79 | return this._countObserver.asObservable();
80 | };
81 | /**
82 | * Stops the observation on the cursor.
83 | */
84 | ObservableCursor.prototype.stop = function () {
85 | var _this = this;
86 | this._zone.run(function () {
87 | _this._runComplete();
88 | });
89 | if (this._hCursor) {
90 | this._hCursor.stop();
91 | }
92 | this._data = [];
93 | this._hCursor = null;
94 | };
95 | /**
96 | * Clears the Observable definition.
97 | * Use this method only when the Observable is still cold, and there are no active subscriptions yet.
98 | */
99 | ObservableCursor.prototype.dispose = function () {
100 | this._observers = null;
101 | this._cursor = null;
102 | };
103 | /**
104 | * Return all matching documents as an Array.
105 | *
106 | * @return {Array} The array with the matching documents.
107 | */
108 | ObservableCursor.prototype.fetch = function () {
109 | return this._cursor.fetch();
110 | };
111 | /**
112 | * Watch a query. Receive callbacks as the result set changes.
113 | * @param {Mongo.ObserveCallbacks} callbacks - The callbacks object.
114 | * @return {Meteor.LiveQueryHandle} The array with the matching documents.
115 | */
116 | ObservableCursor.prototype.observe = function (callbacks) {
117 | return this._cursor.observe(callbacks);
118 | };
119 | /**
120 | * Watch a query. Receive callbacks as the result set changes.
121 | * Only the differences between the old and new documents are passed to the callbacks.
122 | * @param {Mongo.ObserveChangesCallbacks} callbacks - The callbacks object.
123 | * @return {Meteor.LiveQueryHandle} The array with the matching documents.
124 | */
125 | ObservableCursor.prototype.observeChanges = function (callbacks) {
126 | return this._cursor.observeChanges(callbacks);
127 | };
128 | ObservableCursor.prototype._runComplete = function () {
129 | this._countObserver.complete();
130 | this._observers.forEach(function (observer) {
131 | observer.complete();
132 | });
133 | };
134 | ObservableCursor.prototype._runNext = function (data) {
135 | this._countObserver.next(this._data.length);
136 | this._observers.forEach(function (observer) {
137 | observer.next(data);
138 | });
139 | };
140 | ObservableCursor.prototype._addedAt = function (doc, at, before) {
141 | this._data.splice(at, 0, doc);
142 | this._handleChange();
143 | };
144 | ObservableCursor.prototype._changedAt = function (doc, old, at) {
145 | this._data[at] = doc;
146 | this._handleChange();
147 | };
148 | ObservableCursor.prototype._removedAt = function (doc, at) {
149 | this._data.splice(at, 1);
150 | this._handleChange();
151 | };
152 | ObservableCursor.prototype._movedTo = function (doc, fromIndex, toIndex) {
153 | this._data.splice(fromIndex, 1);
154 | this._data.splice(toIndex, 0, doc);
155 | this._handleChange();
156 | };
157 | ObservableCursor.prototype._handleChange = function () {
158 | var _this = this;
159 | this._isDataInitinialized = true;
160 | this._zone.run(function () {
161 | _this._runNext(_this._data);
162 | });
163 | };
164 | ObservableCursor.prototype._observeCursor = function (cursor) {
165 | var _this = this;
166 | return gZone.run(function () { return cursor.observe({
167 | addedAt: _this._addedAt.bind(_this),
168 | changedAt: _this._changedAt.bind(_this),
169 | movedTo: _this._movedTo.bind(_this),
170 | removedAt: _this._removedAt.bind(_this)
171 | }); });
172 | };
173 | return ObservableCursor;
174 | }(Observable));
175 | export { ObservableCursor };
176 | //# sourceMappingURL=ObservableCursor.js.map
--------------------------------------------------------------------------------
/dist/ObservableCursor.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"ObservableCursor.js","sourceRoot":"","sources":["../src/ObservableCursor.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,OAAO,EAAE,UAAU,EAAkB,OAAO,EAAE,MAAM,MAAM,CAAC;AAE3D,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAI1D;IAAyC,oCAAe;IAsBtD;;;;OAIG;IACH,0BAAY,MAAuB;QAAnC,YACE,kBAAM,UAAC,QAAyB;YAC9B,KAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAE/B,EAAE,CAAC,CAAC,CAAC,KAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACnB,KAAI,CAAC,QAAQ,GAAG,KAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YAC9C,CAAC;YAED,MAAM,CAAC,UAAU,CAAC;gBAChB,EAAE,CAAC,CAAC,KAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC;oBAC9B,QAAQ,CAAC,IAAI,CAAC,KAAI,CAAC,KAAK,CAAC,CAAC;gBAC5B,CAAC;gBAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;oBAChC,KAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC;oBACjC,QAAQ,CAAC,IAAI,CAAC,KAAI,CAAC,KAAK,CAAC,CAAC;gBAC5B,CAAC;YACH,CAAC,EAAE,CAAC,CAAC,CAAC;YAEN,MAAM,CAAC;gBACL,cAAc,CAAC,KAAI,CAAC,UAAU,EAC5B,QAAQ,EAAE,cAAM,OAAA,KAAI,CAAC,IAAI,EAAE,EAAX,CAAW,CAAC,CAAC;YACjC,CAAC,CAAC;QACJ,CAAC,CAAC,SAMH;QApDO,WAAK,GAAa,EAAE,CAAC;QAGrB,gBAAU,GAAsB,EAAE,CAAC;QACnC,oBAAc,GAAoB,IAAI,OAAO,EAAU,CAAC;QACxD,0BAAoB,GAAG,KAAK,CAAC;QA2CnC,CAAC,CAAC,MAAM,CAAC,KAAI,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;QAE/C,KAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,KAAI,CAAC,KAAK,GAAG,QAAQ,EAAE,CAAC;;IAC1B,CAAC;IA7CD;;;;;;;;OAQG;IACI,uBAAM,GAAb,UAAiB,MAAuB;QACtC,MAAM,CAAC,IAAI,gBAAgB,CAAI,MAAM,CAAC,CAAC;IACzC,CAAC;IAwCD,sBAAI,oCAAM;QAJV;;;WAGG;aACH;YACE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;QACtB,CAAC;;;OAAA;IAED;;;;;;OAMG;IACH,0CAAe,GAAf;QACE,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,YAAY,EAAE,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,+BAAI,GAAJ;QAAA,iBAWC;QAVC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;YACb,KAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAClB,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACvB,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;IACvB,CAAC;IAED;;;OAGG;IACH,kCAAO,GAAP;QACE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;IAED;;;;OAIG;IACH,gCAAK,GAAL;QACE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IAC9B,CAAC;IAED;;;;OAIG;IACH,kCAAO,GAAP,UAAQ,SAAiB;QACvB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACzC,CAAC;IAED;;;;;OAKG;IACH,yCAAc,GAAd,UAAe,SAAiB;QAC9B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IAChD,CAAC;IAED,uCAAY,GAAZ;QACE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC;QAE/B,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,UAAA,QAAQ;YAC9B,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,mCAAQ,GAAR,UAAS,IAAc;QACrB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAE5C,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,UAAA,QAAQ;YAC9B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,mCAAQ,GAAR,UAAS,GAAG,EAAE,EAAE,EAAE,MAAM;QACtB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IAED,qCAAU,GAAV,UAAW,GAAG,EAAE,GAAG,EAAE,EAAE;QACrB,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC;QACrB,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IAED,qCAAU,GAAV,UAAW,GAAG,EAAE,EAAE;QAChB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACzB,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IAED,mCAAQ,GAAR,UAAS,GAAG,EAAE,SAAS,EAAE,OAAO;QAC9B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IAED,wCAAa,GAAb;QAAA,iBAMC;QALC,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC;QAEjC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;YACb,KAAI,CAAC,QAAQ,CAAC,KAAI,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,yCAAc,GAAd,UAAe,MAAuB;QAAtC,iBAQC;QAPC,MAAM,CAAC,KAAK,CAAC,GAAG,CACd,cAAM,OAAA,MAAM,CAAC,OAAO,CAAC;YACnB,OAAO,EAAE,KAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAI,CAAC;YACjC,SAAS,EAAE,KAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAI,CAAC;YACrC,OAAO,EAAE,KAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAI,CAAC;YACjC,SAAS,EAAE,KAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAI,CAAC;SACtC,CAAC,EALI,CAKJ,CAAC,CAAC;IACR,CAAC;IACH,uBAAC;AAAD,CAAC,AAtLD,CAAyC,UAAU,GAsLlD"}
--------------------------------------------------------------------------------
/dist/bundles/index.umd.js:
--------------------------------------------------------------------------------
1 | (function (global, factory) {
2 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('rxjs')) :
3 | typeof define === 'function' && define.amd ? define(['exports', 'rxjs'], factory) :
4 | (factory((global.meteor = global.meteor || {}, global.meteor.rxjs = {}),global.rxjs));
5 | }(this, (function (exports,rxjs) { 'use strict';
6 |
7 | var subscribeEvents = ['onReady', 'onError', 'onStop'];
8 | function isMeteorCallbacks(callbacks) {
9 | return _.isFunction(callbacks) || isCallbacksObject(callbacks);
10 | }
11 | // Checks if callbacks of {@link CallbacksObject} type.
12 | function isCallbacksObject(callbacks) {
13 | return callbacks && subscribeEvents.some(function (event) {
14 | return _.isFunction(callbacks[event]);
15 | });
16 | }
17 | var g = typeof global === 'object' ? global :
18 | typeof window === 'object' ? window :
19 | typeof self === 'object' ? self : undefined;
20 | var METEOR_RXJS_ZONE = 'meteor-rxjs-zone';
21 | var fakeZone = {
22 | name: METEOR_RXJS_ZONE,
23 | run: function (func) {
24 | return func();
25 | },
26 | fork: function (spec) {
27 | return fakeZone;
28 | }
29 | };
30 | function forkZone() {
31 | if (g.Zone) {
32 | var zone = g.Zone.current;
33 | if (zone.name === METEOR_RXJS_ZONE) {
34 | zone = zone.parent || fakeZone;
35 | }
36 | return zone.fork({ name: METEOR_RXJS_ZONE });
37 | }
38 | return fakeZone;
39 | }
40 | function getZone() {
41 | if (g.Zone) {
42 | var zone = g.Zone.current;
43 | if (zone.name === METEOR_RXJS_ZONE) {
44 | return zone.parent;
45 | }
46 | return zone;
47 | }
48 | }
49 | function removeObserver(observers, observer, onEmpty) {
50 | var index = observers.indexOf(observer);
51 | observers.splice(index, 1);
52 | if (observers.length === 0 && onEmpty) {
53 | onEmpty();
54 | }
55 | }
56 | var gZone = g.Zone ? g.Zone.current : fakeZone;
57 |
58 | var __extends = (undefined && undefined.__extends) || (function () {
59 | var extendStatics = Object.setPrototypeOf ||
60 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
61 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
62 | return function (d, b) {
63 | extendStatics(d, b);
64 | function __() { this.constructor = d; }
65 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
66 | };
67 | })();
68 | var ObservableCursor = /** @class */ (function (_super) {
69 | __extends(ObservableCursor, _super);
70 | /**
71 | * @constructor
72 | * @extends Observable
73 | * @param {Mongo.Cursor} cursor - The Mongo.Cursor to wrap.
74 | */
75 | function ObservableCursor(cursor) {
76 | var _this = _super.call(this, function (observer) {
77 | _this._observers.push(observer);
78 | if (!_this._hCursor) {
79 | _this._hCursor = _this._observeCursor(cursor);
80 | }
81 | Meteor.setTimeout(function () {
82 | if (_this._isDataInitinialized) {
83 | observer.next(_this._data);
84 | }
85 | else if (cursor.count() === 0) {
86 | _this._isDataInitinialized = true;
87 | observer.next(_this._data);
88 | }
89 | }, 0);
90 | return function () {
91 | removeObserver(_this._observers, observer, function () { return _this.stop(); });
92 | };
93 | }) || this;
94 | _this._data = [];
95 | _this._observers = [];
96 | _this._countObserver = new rxjs.Subject();
97 | _this._isDataInitinialized = false;
98 | _.extend(_this, _.omit(cursor, 'count', 'map'));
99 | _this._cursor = cursor;
100 | _this._zone = forkZone();
101 | return _this;
102 | }
103 | /**
104 | * Static method which creates an ObservableCursor from Mongo.Cursor.
105 | * Use this to create an ObservableCursor object from an existing Mongo.Cursor.
106 | * Prefer to create an Cursors from the ObservableCollection instance instead.
107 | *
108 | * @param {Mongo.Cursor} cursor - The Mongo.Cursor to wrap.
109 | * @static
110 | * @returns {ObservableCursor} Wrapped Cursor.
111 | */
112 | ObservableCursor.create = function (cursor) {
113 | return new ObservableCursor(cursor);
114 | };
115 | Object.defineProperty(ObservableCursor.prototype, "cursor", {
116 | /**
117 | * Returns the actual Mongo.Cursor that wrapped by current ObservableCursor instance.
118 | * @return {Mongo.Cursor} The actual MongoDB Cursor.
119 | */
120 | get: function () {
121 | return this._cursor;
122 | },
123 | enumerable: true,
124 | configurable: true
125 | });
126 | /**
127 | * A wrapper for Mongo.Cursor.count() method - returns an Observable of number, which
128 | * triggers each time there is a change in the collection, and exposes the number of
129 | * objects in the collection.
130 | * @returns {Observable} Observable which trigger the callback when the
131 | * count of the object changes.
132 | */
133 | ObservableCursor.prototype.collectionCount = function () {
134 | return this._countObserver.asObservable();
135 | };
136 | /**
137 | * Stops the observation on the cursor.
138 | */
139 | ObservableCursor.prototype.stop = function () {
140 | var _this = this;
141 | this._zone.run(function () {
142 | _this._runComplete();
143 | });
144 | if (this._hCursor) {
145 | this._hCursor.stop();
146 | }
147 | this._data = [];
148 | this._hCursor = null;
149 | };
150 | /**
151 | * Clears the Observable definition.
152 | * Use this method only when the Observable is still cold, and there are no active subscriptions yet.
153 | */
154 | ObservableCursor.prototype.dispose = function () {
155 | this._observers = null;
156 | this._cursor = null;
157 | };
158 | /**
159 | * Return all matching documents as an Array.
160 | *
161 | * @return {Array} The array with the matching documents.
162 | */
163 | ObservableCursor.prototype.fetch = function () {
164 | return this._cursor.fetch();
165 | };
166 | /**
167 | * Watch a query. Receive callbacks as the result set changes.
168 | * @param {Mongo.ObserveCallbacks} callbacks - The callbacks object.
169 | * @return {Meteor.LiveQueryHandle} The array with the matching documents.
170 | */
171 | ObservableCursor.prototype.observe = function (callbacks) {
172 | return this._cursor.observe(callbacks);
173 | };
174 | /**
175 | * Watch a query. Receive callbacks as the result set changes.
176 | * Only the differences between the old and new documents are passed to the callbacks.
177 | * @param {Mongo.ObserveChangesCallbacks} callbacks - The callbacks object.
178 | * @return {Meteor.LiveQueryHandle} The array with the matching documents.
179 | */
180 | ObservableCursor.prototype.observeChanges = function (callbacks) {
181 | return this._cursor.observeChanges(callbacks);
182 | };
183 | ObservableCursor.prototype._runComplete = function () {
184 | this._countObserver.complete();
185 | this._observers.forEach(function (observer) {
186 | observer.complete();
187 | });
188 | };
189 | ObservableCursor.prototype._runNext = function (data) {
190 | this._countObserver.next(this._data.length);
191 | this._observers.forEach(function (observer) {
192 | observer.next(data);
193 | });
194 | };
195 | ObservableCursor.prototype._addedAt = function (doc, at, before) {
196 | this._data.splice(at, 0, doc);
197 | this._handleChange();
198 | };
199 | ObservableCursor.prototype._changedAt = function (doc, old, at) {
200 | this._data[at] = doc;
201 | this._handleChange();
202 | };
203 | ObservableCursor.prototype._removedAt = function (doc, at) {
204 | this._data.splice(at, 1);
205 | this._handleChange();
206 | };
207 | ObservableCursor.prototype._movedTo = function (doc, fromIndex, toIndex) {
208 | this._data.splice(fromIndex, 1);
209 | this._data.splice(toIndex, 0, doc);
210 | this._handleChange();
211 | };
212 | ObservableCursor.prototype._handleChange = function () {
213 | var _this = this;
214 | this._isDataInitinialized = true;
215 | this._zone.run(function () {
216 | _this._runNext(_this._data);
217 | });
218 | };
219 | ObservableCursor.prototype._observeCursor = function (cursor) {
220 | var _this = this;
221 | return gZone.run(function () { return cursor.observe({
222 | addedAt: _this._addedAt.bind(_this),
223 | changedAt: _this._changedAt.bind(_this),
224 | movedTo: _this._movedTo.bind(_this),
225 | removedAt: _this._removedAt.bind(_this)
226 | }); });
227 | };
228 | return ObservableCursor;
229 | }(rxjs.Observable));
230 |
231 | (function (MongoObservable) {
232 | 'use strict';
233 | /**
234 | * Creates a new MongoObservable.Collection from an existing of predefined Mongo.Collection.
235 | * Use this feature to wrap existing collections such as Meteor.users.
236 | * @param {Mongo.Collection} collection - The collection.
237 | * @returns {MongoObservable.Collection} - Wrapped collection.
238 | * @static
239 | */
240 | function fromExisting(collection) {
241 | return new MongoObservable.Collection(collection);
242 | }
243 | MongoObservable.fromExisting = fromExisting;
244 | /**
245 | * A class represents a MongoDB collection in the client side, wrapped with RxJS
246 | * Observables, so you can use it with your Angular 2 easier.
247 | * The wrapper has the same API as Mongo.Collection, only the "find" method returns
248 | * an ObservableCursor instead of regular Mongo.Cursor.
249 | *
250 | * T is a generic type - should be used with the type of the objects inside the collection.
251 | */
252 | var Collection = /** @class */ (function () {
253 | /**
254 | * Creates a new Mongo.Collection instance wrapped with Observable features.
255 | * @param {String | Mongo.Collection} nameOrExisting - The name of the collection. If null, creates an
256 | * unmanaged (unsynchronized) local collection. If provided an instance of existing collection, will
257 | * create a wrapper for the existing Mongo.Collection.
258 | * @param {ConstructorOptions} options - Creation options.
259 | * @constructor
260 | */
261 | function Collection(nameOrExisting, options) {
262 | if (nameOrExisting instanceof Mongo.Collection) {
263 | this._collection = nameOrExisting;
264 | }
265 | else {
266 | this._collection = new Mongo.Collection(nameOrExisting, options);
267 | }
268 | }
269 | Object.defineProperty(Collection.prototype, "collection", {
270 | /**
271 | * Returns the Mongo.Collection object that wrapped with the MongoObservable.Collection.
272 | * @returns {Mongo.Collection} The Collection instance
273 | */
274 | get: function () {
275 | return this._collection;
276 | },
277 | enumerable: true,
278 | configurable: true
279 | });
280 | /**
281 | * Allow users to write directly to this collection from client code, subject to limitations you define.
282 | *
283 | * @returns {Boolean}
284 | */
285 | Collection.prototype.allow = function (options) {
286 | return this._collection.allow(options);
287 | };
288 | /**
289 | * Override allow rules.
290 | *
291 | * @returns {Boolean}
292 | */
293 | Collection.prototype.deny = function (options) {
294 | return this._collection.deny(options);
295 | };
296 | /**
297 | * Returns the Collection object corresponding to this collection from the npm
298 | * mongodb driver module which is wrapped by Mongo.Collection.
299 | *
300 | * @returns {Mongo.Collection} The Collection instance
301 | *
302 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-rawCollection|rawCollection on Meteor documentation}
303 | */
304 | Collection.prototype.rawCollection = function () {
305 | return this._collection.rawCollection();
306 | };
307 | /**
308 | * Returns the Db object corresponding to this collection's database connection from the
309 | * npm mongodb driver module which is wrapped by Mongo.Collection.
310 | *
311 | * @returns {Mongo.Db} The Db instance
312 | *
313 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-rawDatabase|rawDatabase on Meteor documentation}
314 | */
315 | Collection.prototype.rawDatabase = function () {
316 | return this._collection.rawDatabase();
317 | };
318 | /**
319 | * Insert a document in the collection.
320 | *
321 | * @param {T} doc - The document to insert. May not yet have an _id
322 | * attribute, in which case Meteor will generate one for you.
323 | * @returns {Observable} Observable which completes with the inserted ObjectId
324 | *
325 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-insert|insert on Meteor documentation}
326 | */
327 | Collection.prototype.insert = function (doc) {
328 | var observers = [];
329 | var obs = this._createObservable(observers);
330 | this._collection.insert(doc, function (error, docId) {
331 | observers.forEach(function (observer) {
332 | error ? observer.error(error) :
333 | observer.next(docId);
334 | observer.complete();
335 | });
336 | });
337 | return obs;
338 | };
339 | /**
340 | * Remove documents from the collection.
341 | *
342 | * @param {Collection~MongoQuerySelector} selector - Specifies which documents to modify
343 | * @returns {Observable} Observable which completes with the number of affected rows
344 | *
345 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-remove|remove on Meteor documentation}
346 | */
347 | Collection.prototype.remove = function (selector) {
348 | var observers = [];
349 | var obs = this._createObservable(observers);
350 | this._collection.remove(selector, function (error, removed) {
351 | observers.forEach(function (observer) {
352 | error ? observer.error(error) :
353 | observer.next(removed);
354 | observer.complete();
355 | });
356 | });
357 | return obs;
358 | };
359 | /**
360 | * Modify one or more documents in the collection.
361 | *
362 | * @param {Collection~MongoQuerySelector} selector - Specifies which documents to modify
363 | * @param {Modifier} modifier - Specifies how to modify the documents
364 | * @param {MongoUpdateOptions} options - Update options
365 | * first argument and, if no error, the number of affected documents as the second
366 | * @returns {Observable} Observable which completes with the number of affected rows
367 | *
368 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-update|update on Meteor documentation}
369 | */
370 | Collection.prototype.update = function (selector, modifier, options) {
371 | var observers = [];
372 | var obs = this._createObservable(observers);
373 | this._collection.update(selector, modifier, options, function (error, updated) {
374 | observers.forEach(function (observer) {
375 | error ? observer.error(error) :
376 | observer.next(updated);
377 | observer.complete();
378 | });
379 | });
380 | return obs;
381 | };
382 | /**
383 | * Finds the first document that matches the selector, as ordered by sort and skip options.
384 | *
385 | * @param {Collection~MongoQuerySelector} selector - Specifies which documents to modify
386 | * @param {Modifier} modifier - Specifies how to modify the documents
387 | * @param {MongoUpsertOptions} options - Upsert options
388 | * first argument and, if no error, the number of affected documents as the second.
389 | * @returns {Observable<{numberAffected, insertedId}>} Observable which completes with an
390 | * Object that contain the keys numberAffected and insertedId.
391 | *
392 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-upsert|upsert on Meteor documentation}
393 | */
394 | Collection.prototype.upsert = function (selector, modifier, options) {
395 | var observers = [];
396 | var obs = this._createObservable(observers);
397 | this._collection.upsert(selector, modifier, options, function (error, affected) {
398 | observers.forEach(function (observer) {
399 | error ? observer.error(error) :
400 | observer.next(affected);
401 | observer.complete();
402 | });
403 | });
404 | return obs;
405 | };
406 | /**
407 | * Method has the same notation as Mongo.Collection.find, only returns Observable.
408 | *
409 | * @param {Collection~MongoQuerySelector} selector - A query describing the documents to find
410 | * @param {Collection~MongoQueryOptions} options - Query options, such as sort, limit, etc.
411 | * @returns {ObservableCursor} RxJS Observable wrapped with Meteor features.
412 | * @example Using Angular2 Component
413 | * const MyCollection = MongoObservable.Collection("myCollection");
414 | *
415 | * class MyComponent {
416 | * private myData: ObservableCursor;
417 | *
418 | * constructor() {
419 | * this.myData = MyCollection.find({}, {limit: 10});
420 | * }
421 | * }
422 | *
423 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-find|find on Meteor documentation}
424 | */
425 | Collection.prototype.find = function (selector, options) {
426 | var cursor = this._collection.find.apply(this._collection, arguments);
427 | return ObservableCursor.create(cursor);
428 | };
429 | /**
430 | * Finds the first document that matches the selector, as ordered by sort and skip options.
431 | *
432 | * @param {Collection~MongoQuerySelector} selector - A query describing the documents to find
433 | * @param {Collection~MongoQueryOptions} options - Query options, such as sort, limit, etc.
434 | * @returns {any} The first object, or `undefined` in case of non-existing object.
435 | *
436 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-findOne|findOne on Meteor documentation}
437 | */
438 | Collection.prototype.findOne = function (selector, options) {
439 | return this._collection.findOne.apply(this._collection, arguments);
440 | };
441 | Collection.prototype._createObservable = function (observers) {
442 | return rxjs.Observable.create(function (observer) {
443 | observers.push(observer);
444 | return function () {
445 | removeObserver(observers, observer);
446 | };
447 | });
448 | };
449 | return Collection;
450 | }());
451 | MongoObservable.Collection = Collection;
452 | })(exports.MongoObservable || (exports.MongoObservable = {}));
453 | /**
454 | * An options object for MongoDB queries.
455 | * @typedef {Object} Collection~MongoQueryOptions
456 | * @property {Object} sort - Sort order (default: natural order)
457 | * @property {Number} skip - Number of results to skip at the beginning
458 | * @property {Object} fields - Dictionary of fields to return or exclude.
459 | * @property {Boolean} reactive - (Client only) Default true; pass false to disable reactivity
460 | * @property {Function} transform - Overrides transform on the Collection for this cursor. Pass null to disable transformation.
461 | */
462 | /**
463 | * A MongoDB query selector representation.
464 | * @typedef {(Mongo.Selector|Mongo.ObjectID|string)} Collection~MongoQuerySelector
465 | */
466 | /**
467 | * A MongoDB query options for upsert action
468 | * @typedef {Object} Collection~MongoUpsertOptions
469 | * @property {Boolean} multi - True to modify all matching documents;
470 | * false to only modify one of the matching documents (the default).
471 | */
472 | /**
473 | * A MongoDB query options for update action
474 | * @typedef {Object} Collection~MongoUpdateOptions
475 | * @property {Boolean} multi - True to modify all matching documents;
476 | * @property {Boolean} upsert - True to use upsert logic.
477 | */
478 |
479 | var liveSubscriptions = [];
480 | function throwInvalidCallback(method) {
481 | throw new Error("Invalid " + method + " arguments:\n your last param can't be a callback function,\n please remove it and use \".subscribe\" of the Observable!");
482 | }
483 | /**
484 | * This is a class with static methods that wrap Meteor's API and return RxJS
485 | * Observables. The methods' signatures are the same as Meteor's, with the ]
486 | * exception that the callbacks are handled by Meteor-rxjs. Instead of
487 | * providing callbacks, you need to subscribe to the observables that are
488 | * returned. The methods that are wrapped in MeteorObservable are
489 | * [Meteor.call](https://docs.meteor.com/api/methods.html#Meteor-call),
490 | * [Meteor.autorun](https://docs.meteor.com/api/tracker.html#Tracker-autorun)
491 | * and [Meteor.subscribe](https://docs.meteor.com/api/pubsub.html#Meteor-subscribe).
492 | */
493 | var MeteorObservable = /** @class */ (function () {
494 | function MeteorObservable() {
495 | }
496 | /**
497 | * Invokes a [Meteor Method](https://docs.meteor.com/api/methods.html)
498 | * defined on the server, passing any number of arguments. This method has
499 | * the same signature as
500 | * [Meteor.call](https://docs.meteor.com/api/methods.html#Meteor-call), only
501 | * without the callbacks:
502 | * MeteorObservable.call(name, [...args])
503 | *
504 | *
505 | * @param {string} name - Name of the method in the Meteor server
506 | * @param {any} args - Parameters that will be forwarded to the method.
507 | * after the func call to initiate change detection.
508 | * @returns {Observable} - RxJS Observable, which completes when the
509 | * server returns a response.
510 | *
511 | * @example Example using Angular2 Component
512 | * class MyComponent {
513 | * constructor() {
514 | *
515 | * }
516 | *
517 | * doAction(payload) {
518 | * MeteorObservable.call("myData", payload).subscribe((response) => {
519 | * // Handle success and response from server!
520 | * }, (err) => {
521 | * // Handle error
522 | * });
523 | * }
524 | * }
525 | */
526 | MeteorObservable.call = function (name) {
527 | var args = [];
528 | for (var _i = 1; _i < arguments.length; _i++) {
529 | args[_i - 1] = arguments[_i];
530 | }
531 | var lastParam = args[args.length - 1];
532 | if (isMeteorCallbacks(lastParam)) {
533 | throwInvalidCallback('MeteorObservable.call');
534 | }
535 | var zone = forkZone();
536 | return rxjs.Observable.create(function (observer) {
537 | Meteor.call.apply(Meteor, [name].concat(args.concat([
538 | function (error, result) {
539 | zone.run(function () {
540 | error ? observer.error(error) :
541 | observer.next(result);
542 | observer.complete();
543 | });
544 | }
545 | ])));
546 | });
547 | };
548 | /**
549 | * When you subscribe to a collection, it tells the server to send records to
550 | * the client. This method has the same signature as
551 | * [Meteor.subscribe](https://docs.meteor.com/api/pubsub.html#Meteor-subscribe),
552 | * except without the callbacks again:
553 | * subscribe(name, [...args])
554 | *
555 | * You can use this method from any Angular2 element - such as Component,
556 | * Pipe or Service.
557 | *
558 | * @param {string} name - Name of the publication in the Meteor server
559 | * @param {any} args - Parameters that will be forwarded to the publication.
560 | * after the func call to initiate change detection.
561 | * @returns {Observable} - RxJS Observable, which completes when the
562 | * subscription is ready.
563 | *
564 | * @example Example using Angular2 Service
565 | * class MyService {
566 | * private meteorSubscription: Observable;
567 | *
568 | * constructor() {
569 | *
570 | * }
571 | *
572 | * subscribeToData() {
573 | * this.meteorSubscription = MeteorObservable.subscribe("myData").subscribe(() => {
574 | * // Subscription is ready!
575 | * });
576 | * }
577 | *
578 | * unsubscribeToData() {
579 | * this.meteorSubscription.unsubscribe();
580 | * }
581 | * }
582 | *
583 | * @example Example using Angular2 Component
584 | * class MyComponent implements OnInit, OnDestroy {
585 | * private meteorSubscription: Observable;
586 | *
587 | * constructor() {
588 | *
589 | * }
590 | *
591 | * ngOnInit() {
592 | * this.meteorSubscription = MeteorObservable.subscribe("myData").subscribe(() => {
593 | * // Subscription is ready!
594 | * });
595 | * }
596 | *
597 | * ngOnDestroy() {
598 | * this.meteorSubscription.unsubscribe();
599 | * }
600 | * }
601 | *
602 | * @see {@link http://docs.meteor.com/api/pubsub.html|Publications in Meteor documentation}
603 | */
604 | MeteorObservable.subscribe = function (name) {
605 | var args = [];
606 | for (var _i = 1; _i < arguments.length; _i++) {
607 | args[_i - 1] = arguments[_i];
608 | }
609 | var lastParam = args[args.length - 1];
610 | if (isMeteorCallbacks(lastParam)) {
611 | throwInvalidCallback('MeteorObservable.subscribe');
612 | }
613 | var zone = forkZone();
614 | var observers = [];
615 | var subscribe = function () {
616 | return Meteor.subscribe.apply(Meteor, [name].concat(args.concat([{
617 | onError: function (error) {
618 | zone.run(function () {
619 | observers.forEach(function (observer) { return observer.error(error); });
620 | });
621 | },
622 | onReady: function () {
623 | zone.run(function () {
624 | observers.forEach(function (observer) { return observer.next(); });
625 | });
626 | }
627 | }
628 | ])));
629 | };
630 | var subHandler = null;
631 | return rxjs.Observable.create(function (observer) {
632 | observers.push(observer);
633 | // Execute subscribe lazily.
634 | if (subHandler === null) {
635 | subHandler = subscribe();
636 | if (liveSubscriptions.find(function (sub) { return sub === subHandler.subscriptionId; })) {
637 | // subscription already exists, call observer.next() since Meteor won't.
638 | observer.next();
639 | }
640 | else {
641 | liveSubscriptions.push(subHandler.subscriptionId);
642 | }
643 | }
644 | return function () {
645 | removeObserver(observers, observer, function () {
646 | // remove subscription from liveSubscriptions list
647 | var i = liveSubscriptions.findIndex(function (sub) { return sub === subHandler.subscriptionId; });
648 | if (i > -1) {
649 | liveSubscriptions.splice(i, 1);
650 | }
651 | subHandler.stop();
652 | });
653 | };
654 | });
655 | };
656 | /**
657 | * Allows you to run a function every time there is a change is a reactive
658 | * data sources. This method has the same signature as
659 | * [Meteor.autorun](https://docs.meteor.com/api/tracker.html#Tracker-autorun),
660 | * only without the callback:
661 | * MeteorObservable.autorun()
662 | *
663 | * @returns {Observable} - RxJS Observable, which trigger the subscription callback
664 | * each time that Meteor Tracker detects a change.
665 | * @example Example using Angular2 Component
666 | * class MyComponent {
667 | * constructor() {
668 | *
669 | * }
670 | *
671 | * doAction(payload) {
672 | * MeteorObservable.autorun().subscribe(() => {
673 | * // Handle Tracker autorun change
674 | * });
675 | * }
676 | * }
677 | */
678 | MeteorObservable.autorun = function () {
679 | var zone = forkZone();
680 | var observers = [];
681 | var autorun = function () {
682 | return Tracker.autorun(function (computation) {
683 | zone.run(function () {
684 | observers.forEach(function (observer) { return observer.next(computation); });
685 | });
686 | });
687 | };
688 | var handler = null;
689 | return rxjs.Observable.create(function (observer) {
690 | observers.push(observer);
691 | // Execute autorun lazily.
692 | if (handler === null) {
693 | handler = autorun();
694 | }
695 | return function () {
696 | removeObserver(observers, observer, function () { return handler.stop(); });
697 | };
698 | });
699 | };
700 | return MeteorObservable;
701 | }());
702 |
703 | var __extends$1 = (undefined && undefined.__extends) || (function () {
704 | var extendStatics = Object.setPrototypeOf ||
705 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
706 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
707 | return function (d, b) {
708 | extendStatics(d, b);
709 | function __() { this.constructor = d; }
710 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
711 | };
712 | })();
713 | var zoneOperator = function (zone) { return function (source) { return source.lift(new ZoneOperator(zone || getZone())); }; };
714 | var ZoneOperator = /** @class */ (function () {
715 | function ZoneOperator(zone) {
716 | this.zone = zone;
717 | }
718 | ZoneOperator.prototype.call = function (subscriber, source) {
719 | return source._subscribe(new ZoneSubscriber(subscriber, this.zone));
720 | };
721 | return ZoneOperator;
722 | }());
723 | var ZoneSubscriber = /** @class */ (function (_super) {
724 | __extends$1(ZoneSubscriber, _super);
725 | function ZoneSubscriber(destination, zone) {
726 | var _this = _super.call(this, destination) || this;
727 | _this.zone = zone;
728 | return _this;
729 | }
730 | ZoneSubscriber.prototype._next = function (value) {
731 | var _this = this;
732 | this.zone.run(function () {
733 | _this.destination.next(value);
734 | });
735 | };
736 | ZoneSubscriber.prototype._complete = function () {
737 | var _this = this;
738 | this.zone.run(function () {
739 | _this.destination.complete();
740 | });
741 | };
742 | ZoneSubscriber.prototype._error = function (err) {
743 | var _this = this;
744 | this.zone.run(function () {
745 | _this.destination.error(err);
746 | });
747 | };
748 | return ZoneSubscriber;
749 | }(rxjs.Subscriber));
750 |
751 | exports.MeteorObservable = MeteorObservable;
752 | exports.ObservableCursor = ObservableCursor;
753 | exports.zoneOperator = zoneOperator;
754 |
755 | Object.defineProperty(exports, '__esModule', { value: true });
756 |
757 | })));
758 |
--------------------------------------------------------------------------------
/dist/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './ObservableCollection';
2 | export * from './MeteorObservable';
3 | export * from './ObservableCursor';
4 | export * from './zone';
5 |
--------------------------------------------------------------------------------
/dist/index.js:
--------------------------------------------------------------------------------
1 | export * from './ObservableCollection';
2 | export * from './MeteorObservable';
3 | export * from './ObservableCursor';
4 | export * from './zone';
5 | //# sourceMappingURL=index.js.map
--------------------------------------------------------------------------------
/dist/index.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,QAAQ,CAAC"}
--------------------------------------------------------------------------------
/dist/utils.d.ts:
--------------------------------------------------------------------------------
1 | import { Subscriber } from 'rxjs';
2 | export declare type CallbacksObject = {
3 | onReady?: Function;
4 | onError?: Function;
5 | onStop?: Function;
6 | };
7 | export declare type MeteorCallbacks = ((...args) => any) | CallbacksObject;
8 | export declare const subscribeEvents: string[];
9 | export declare function isMeteorCallbacks(callbacks: any): boolean;
10 | export declare function isCallbacksObject(callbacks: any): boolean;
11 | export declare const g: any;
12 | export declare function forkZone(): any;
13 | export declare function getZone(): any;
14 | export declare function removeObserver(observers: Subscriber[], observer: Subscriber, onEmpty?: Function): void;
15 | export declare const gZone: any;
16 |
--------------------------------------------------------------------------------
/dist/utils.js:
--------------------------------------------------------------------------------
1 | export var subscribeEvents = ['onReady', 'onError', 'onStop'];
2 | export function isMeteorCallbacks(callbacks) {
3 | return _.isFunction(callbacks) || isCallbacksObject(callbacks);
4 | }
5 | // Checks if callbacks of {@link CallbacksObject} type.
6 | export function isCallbacksObject(callbacks) {
7 | return callbacks && subscribeEvents.some(function (event) {
8 | return _.isFunction(callbacks[event]);
9 | });
10 | }
11 | export var g = typeof global === 'object' ? global :
12 | typeof window === 'object' ? window :
13 | typeof self === 'object' ? self : undefined;
14 | var METEOR_RXJS_ZONE = 'meteor-rxjs-zone';
15 | var fakeZone = {
16 | name: METEOR_RXJS_ZONE,
17 | run: function (func) {
18 | return func();
19 | },
20 | fork: function (spec) {
21 | return fakeZone;
22 | }
23 | };
24 | export function forkZone() {
25 | if (g.Zone) {
26 | var zone = g.Zone.current;
27 | if (zone.name === METEOR_RXJS_ZONE) {
28 | zone = zone.parent || fakeZone;
29 | }
30 | return zone.fork({ name: METEOR_RXJS_ZONE });
31 | }
32 | return fakeZone;
33 | }
34 | export function getZone() {
35 | if (g.Zone) {
36 | var zone = g.Zone.current;
37 | if (zone.name === METEOR_RXJS_ZONE) {
38 | return zone.parent;
39 | }
40 | return zone;
41 | }
42 | }
43 | export function removeObserver(observers, observer, onEmpty) {
44 | var index = observers.indexOf(observer);
45 | observers.splice(index, 1);
46 | if (observers.length === 0 && onEmpty) {
47 | onEmpty();
48 | }
49 | }
50 | export var gZone = g.Zone ? g.Zone.current : fakeZone;
51 | //# sourceMappingURL=utils.js.map
--------------------------------------------------------------------------------
/dist/utils.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAYA,MAAM,CAAC,IAAM,eAAe,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAEhE,MAAM,4BAA4B,SAAc;IAC9C,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,iBAAiB,CAAC,SAAS,CAAC,CAAC;AACjE,CAAC;AAED,uDAAuD;AACvD,MAAM,4BAA4B,SAAc;IAC9C,MAAM,CAAC,SAAS,IAAI,eAAe,CAAC,IAAI,CAAC,UAAC,KAAK;QAC7C,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACL,CAAC;AAGD,MAAM,CAAC,IAAM,CAAC,GACZ,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACnC,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACnC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAElD,IAAM,gBAAgB,GAAG,kBAAkB,CAAC;AAE5C,IAAM,QAAQ,GAAG;IACf,IAAI,EAAE,gBAAgB;IACtB,GAAG,YAAC,IAAc;QAChB,MAAM,CAAC,IAAI,EAAE,CAAC;IAChB,CAAC;IACD,IAAI,YAAC,IAAS;QACZ,MAAM,CAAC,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC;AAEF,MAAM;IACJ,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACX,IAAI,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;QAC1B,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC,CAAC;YACnC,IAAI,GAAG,IAAI,CAAC,MAAM,IAAI,QAAQ,CAAC;QACjC,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAC/C,CAAC;IACD,MAAM,CAAC,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM;IACJ,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACX,IAAI,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;QAC1B,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC,CAAC;YACnC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;QACrB,CAAC;QACD,MAAM,CAAC,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,yBAAyB,SAA4B,EAC5B,QAAyB,EACzB,OAAkB;IAC/C,IAAI,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC3B,EAAE,CAAC,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC;QACtC,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,IAAM,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC"}
--------------------------------------------------------------------------------
/dist/zone.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { Observable } from 'rxjs';
3 | export declare const zoneOperator: (zone?: Zone) => (source: Observable) => Observable<{}>;
4 |
--------------------------------------------------------------------------------
/dist/zone.js:
--------------------------------------------------------------------------------
1 | var __extends = (this && this.__extends) || (function () {
2 | var extendStatics = Object.setPrototypeOf ||
3 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
4 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
5 | return function (d, b) {
6 | extendStatics(d, b);
7 | function __() { this.constructor = d; }
8 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
9 | };
10 | })();
11 | import { Subscriber } from 'rxjs';
12 | import { getZone } from './utils';
13 | export var zoneOperator = function (zone) { return function (source) { return source.lift(new ZoneOperator(zone || getZone())); }; };
14 | var ZoneOperator = /** @class */ (function () {
15 | function ZoneOperator(zone) {
16 | this.zone = zone;
17 | }
18 | ZoneOperator.prototype.call = function (subscriber, source) {
19 | return source._subscribe(new ZoneSubscriber(subscriber, this.zone));
20 | };
21 | return ZoneOperator;
22 | }());
23 | var ZoneSubscriber = /** @class */ (function (_super) {
24 | __extends(ZoneSubscriber, _super);
25 | function ZoneSubscriber(destination, zone) {
26 | var _this = _super.call(this, destination) || this;
27 | _this.zone = zone;
28 | return _this;
29 | }
30 | ZoneSubscriber.prototype._next = function (value) {
31 | var _this = this;
32 | this.zone.run(function () {
33 | _this.destination.next(value);
34 | });
35 | };
36 | ZoneSubscriber.prototype._complete = function () {
37 | var _this = this;
38 | this.zone.run(function () {
39 | _this.destination.complete();
40 | });
41 | };
42 | ZoneSubscriber.prototype._error = function (err) {
43 | var _this = this;
44 | this.zone.run(function () {
45 | _this.destination.error(err);
46 | });
47 | };
48 | return ZoneSubscriber;
49 | }(Subscriber));
50 | //# sourceMappingURL=zone.js.map
--------------------------------------------------------------------------------
/dist/zone.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"zone.js","sourceRoot":"","sources":["../src/zone.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,OAAO,EAA4B,UAAU,EAAE,MAAM,MAAM,CAAC;AAE5D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,CAAC,IAAM,YAAY,GAAG,UAAI,IAAW,IAAK,OAAA,UAAC,MAAqB,IAAK,OAAA,MAAM,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC,EAAhD,CAAgD,EAA3E,CAA2E,CAAC;AAG5H;IACE,sBAAoB,IAAU;QAAV,SAAI,GAAJ,IAAI,CAAM;IAC9B,CAAC;IAED,2BAAI,GAAJ,UAAK,UAAyB,EAAE,MAAW;QACzC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACtE,CAAC;IACH,mBAAC;AAAD,CAAC,AAPD,IAOC;AAED;IAAgC,kCAAa;IAC3C,wBAAY,WAA0B,EAClB,IAAU;QAD9B,YAEE,kBAAM,WAAW,CAAC,SACnB;QAFmB,UAAI,GAAJ,IAAI,CAAM;;IAE9B,CAAC;IAES,8BAAK,GAAf,UAAgB,KAAQ;QAAxB,iBAIC;QAHC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;YACZ,KAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC;IAES,kCAAS,GAAnB;QAAA,iBAIC;QAHC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;YACZ,KAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC;QAC9B,CAAC,CAAC,CAAC;IACL,CAAC;IAES,+BAAM,GAAhB,UAAiB,GAAS;QAA1B,iBAIC;QAHC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;YACZ,KAAI,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;IACL,CAAC;IACH,qBAAC;AAAD,CAAC,AAvBD,CAAgC,UAAU,GAuBzC"}
--------------------------------------------------------------------------------
/docs/MeteorObservable.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## MeteorObservable
4 | This is a class with static methods that wrap Meteor's API and return RxJS
5 | Observables. The methods' signatures are the same as Meteor's, with the ]
6 | exception that the callbacks are handled by Meteor-rxjs. Instead of
7 | providing callbacks, you need to subscribe to the observables that are
8 | returned. The methods that are wrapped in MeteorObservable are
9 | [Meteor.call](https://docs.meteor.com/api/methods.html#Meteor-call),
10 | [Meteor.autorun](https://docs.meteor.com/api/tracker.html#Tracker-autorun)
11 | and [Meteor.subscribe](https://docs.meteor.com/api/pubsub.html#Meteor-subscribe).
12 |
13 | **Kind**: global class
14 |
15 | * [MeteorObservable](#MeteorObservable)
16 | * [.call(name, ...args)](#MeteorObservable.call) ⇒ Observable.<T>
17 | * [.subscribe(name, ...args)](#MeteorObservable.subscribe) ⇒ Observable
18 | * [.autorun()](#MeteorObservable.autorun) ⇒ Observable.<T>
19 |
20 |
21 |
22 | ### MeteorObservable.call(name, ...args) ⇒ Observable.<T>
23 | Invokes a [Meteor Method](https://docs.meteor.com/api/methods.html)
24 | defined on the server, passing any number of arguments. This method has
25 | the same signature as
26 | [Meteor.call](https://docs.meteor.com/api/methods.html#Meteor-call), only
27 | without the callbacks:
28 | MeteorObservable.call(name, [...args])
29 |
30 | **Kind**: static method of [MeteorObservable
](#MeteorObservable)
31 | **Returns**: Observable.<T>
- - RxJS Observable, which completes when the
32 | server returns a response.
33 |
34 | | Param | Type | Description |
35 | | --- | --- | --- |
36 | | name | string
| Name of the method in the Meteor server |
37 | | ...args | any
| Parameters that will be forwarded to the method. after the func call to initiate change detection. |
38 |
39 | **Example** *(Example using Angular2 Component)*
40 | ```js
41 | class MyComponent {
42 | constructor() {
43 |
44 | }
45 |
46 | doAction(payload) {
47 | MeteorObservable.call("myData", payload).subscribe((response) => {
48 | // Handle success and response from server!
49 | }, (err) => {
50 | // Handle error
51 | });
52 | }
53 | }
54 | ```
55 |
56 |
57 | ### MeteorObservable.subscribe(name, ...args) ⇒ Observable
58 | When you subscribe to a collection, it tells the server to send records to
59 | the client. This method has the same signature as
60 | [Meteor.subscribe](https://docs.meteor.com/api/pubsub.html#Meteor-subscribe),
61 | except without the callbacks again:
62 | subscribe(name, [...args])
63 |
64 | You can use this method from any Angular2 element - such as Component,
65 | Pipe or Service.
66 |
67 | **Kind**: static method of [MeteorObservable
](#MeteorObservable)
68 | **Returns**: Observable
- - RxJS Observable, which completes when the
69 | subscription is ready.
70 | **See**: [Publications in Meteor documentation](http://docs.meteor.com/api/pubsub.html)
71 |
72 | | Param | Type | Description |
73 | | --- | --- | --- |
74 | | name | string
| Name of the publication in the Meteor server |
75 | | ...args | any
| Parameters that will be forwarded to the publication. after the func call to initiate change detection. |
76 |
77 | **Example** *(Example using Angular2 Service)*
78 | ```js
79 | class MyService {
80 | private meteorSubscription: Observable;
81 |
82 | constructor() {
83 |
84 | }
85 |
86 | subscribeToData() {
87 | this.meteorSubscription = MeteorObservable.subscribe("myData").subscribe(() => {
88 | // Subscription is ready!
89 | });
90 | }
91 |
92 | unsubscribeToData() {
93 | this.meteorSubscription.unsubscribe();
94 | }
95 | }
96 |
97 |
98 | ```
99 | **Example** *(Example using Angular2 Component)*
100 | ```js
101 | class MyComponent implements OnInit, OnDestroy {
102 | private meteorSubscription: Observable;
103 |
104 | constructor() {
105 |
106 | }
107 |
108 | ngOnInit() {
109 | this.meteorSubscription = MeteorObservable.subscribe("myData").subscribe(() => {
110 | // Subscription is ready!
111 | });
112 | }
113 |
114 | ngOnDestroy() {
115 | this.meteorSubscription.unsubscribe();
116 | }
117 | }
118 |
119 |
120 | ```
121 |
122 |
123 | ### MeteorObservable.autorun() ⇒ Observable.<T>
124 | Allows you to run a function every time there is a change is a reactive
125 | data sources. This method has the same signature as
126 | [Meteor.autorun](https://docs.meteor.com/api/tracker.html#Tracker-autorun),
127 | only without the callback:
128 | MeteorObservable.autorun()
129 |
130 | **Kind**: static method of [MeteorObservable
](#MeteorObservable)
131 | **Returns**: Observable.<T>
- - RxJS Observable, which trigger the subscription callback
132 | each time that Meteor Tracker detects a change.
133 | **Example** *(Example using Angular2 Component)*
134 | ```js
135 | class MyComponent {
136 | constructor() {
137 |
138 | }
139 |
140 | doAction(payload) {
141 | MeteorObservable.autorun().subscribe(() => {
142 | // Handle Tracker autorun change
143 | });
144 | }
145 | }
146 | ```
147 |
--------------------------------------------------------------------------------
/docs/ObservableCollection.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Collection
4 | A class represents a MongoDB collection in the client side, wrapped with RxJS
5 | Observables, so you can use it with your Angular 2 easier.
6 | The wrapper has the same API as Mongo.Collection, only the "find" method returns
7 | an ObservableCursor instead of regular Mongo.Cursor.
8 |
9 | T is a generic type - should be used with the type of the objects inside the collection.
10 |
11 | **Kind**: global class
12 |
13 | * [Collection](#Collection)
14 | * [new Collection(nameOrExisting, options)](#new_Collection_new)
15 | * _instance_
16 | * [.collection](#Collection+collection) ⇒ Mongo.Collection.<T>
17 | * [.allow()](#Collection+allow) ⇒ Boolean
18 | * [.deny()](#Collection+deny) ⇒ Boolean
19 | * [.rawCollection()](#Collection+rawCollection) ⇒ Mongo.Collection
20 | * [.rawDatabase()](#Collection+rawDatabase) ⇒ Mongo.Db
21 | * [.insert(doc)](#Collection+insert) ⇒ Observable.<string>
22 | * [.remove(selector)](#Collection+remove) ⇒ Observable.<Number>
23 | * [.update(selector, modifier, options)](#Collection+update) ⇒ Observable.<Number>
24 | * [.upsert(selector, modifier, options)](#Collection+upsert) ⇒ Observable.<{numberAffected, insertedId}>
25 | * [.find(selector, options)](#Collection+find) ⇒ ObservableCursor.<T>
26 | * [.findOne(selector, options)](#Collection+findOne) ⇒ any
27 | * _inner_
28 | * [~MongoQueryOptions](#Collection..MongoQueryOptions) : Object
29 | * [~MongoQuerySelector](#Collection..MongoQuerySelector) : Mongo.Selector
\| Mongo.ObjectID
\| string
30 | * [~MongoUpsertOptions](#Collection..MongoUpsertOptions) : Object
31 | * [~MongoUpdateOptions](#Collection..MongoUpdateOptions) : Object
32 |
33 |
34 |
35 | ### new Collection(nameOrExisting, options)
36 | Creates a new Mongo.Collection instance wrapped with Observable features.
37 |
38 |
39 | | Param | Type | Description |
40 | | --- | --- | --- |
41 | | nameOrExisting | String
\| Mongo.Collection
| The name of the collection. If null, creates an unmanaged (unsynchronized) local collection. If provided an instance of existing collection, will create a wrapper for the existing Mongo.Collection. |
42 | | options | ConstructorOptions
| Creation options. |
43 |
44 |
45 |
46 | ### collection.collection ⇒ Mongo.Collection.<T>
47 | Returns the Mongo.Collection object that wrapped with the MongoObservable.Collection.
48 |
49 | **Kind**: instance property of [Collection
](#Collection)
50 | **Returns**: Mongo.Collection.<T>
- The Collection instance
51 |
52 |
53 | ### collection.allow() ⇒ Boolean
54 | Allow users to write directly to this collection from client code, subject to limitations you define.
55 |
56 | **Kind**: instance method of [Collection
](#Collection)
57 |
58 |
59 | ### collection.deny() ⇒ Boolean
60 | Override allow rules.
61 |
62 | **Kind**: instance method of [Collection
](#Collection)
63 |
64 |
65 | ### collection.rawCollection() ⇒ Mongo.Collection
66 | Returns the Collection object corresponding to this collection from the npm
67 | mongodb driver module which is wrapped by Mongo.Collection.
68 |
69 | **Kind**: instance method of [Collection
](#Collection)
70 | **Returns**: Mongo.Collection
- The Collection instance
71 | **See**: [rawCollection on Meteor documentation](https://docs.meteor.com/api/collections.html#Mongo-Collection-rawCollection)
72 |
73 |
74 | ### collection.rawDatabase() ⇒ Mongo.Db
75 | Returns the Db object corresponding to this collection's database connection from the
76 | npm mongodb driver module which is wrapped by Mongo.Collection.
77 |
78 | **Kind**: instance method of [Collection
](#Collection)
79 | **Returns**: Mongo.Db
- The Db instance
80 | **See**: [rawDatabase on Meteor documentation](https://docs.meteor.com/api/collections.html#Mongo-Collection-rawDatabase)
81 |
82 |
83 | ### collection.insert(doc) ⇒ Observable.<string>
84 | Insert a document in the collection.
85 |
86 | **Kind**: instance method of [Collection
](#Collection)
87 | **Returns**: Observable.<string>
- Observable which completes with the inserted ObjectId
88 | **See**: [insert on Meteor documentation](https://docs.meteor.com/api/collections.html#Mongo-Collection-insert)
89 |
90 | | Param | Type | Description |
91 | | --- | --- | --- |
92 | | doc | T
| The document to insert. May not yet have an _id attribute, in which case Meteor will generate one for you. |
93 |
94 |
95 |
96 | ### collection.remove(selector) ⇒ Observable.<Number>
97 | Remove documents from the collection.
98 |
99 | **Kind**: instance method of [Collection
](#Collection)
100 | **Returns**: Observable.<Number>
- Observable which completes with the number of affected rows
101 | **See**: [remove on Meteor documentation](https://docs.meteor.com/api/collections.html#Mongo-Collection-remove)
102 |
103 | | Param | Type | Description |
104 | | --- | --- | --- |
105 | | selector | [MongoQuerySelector
](#Collection..MongoQuerySelector) | Specifies which documents to modify |
106 |
107 |
108 |
109 | ### collection.update(selector, modifier, options) ⇒ Observable.<Number>
110 | Modify one or more documents in the collection.
111 |
112 | **Kind**: instance method of [Collection
](#Collection)
113 | **Returns**: Observable.<Number>
- Observable which completes with the number of affected rows
114 | **See**: [update on Meteor documentation](https://docs.meteor.com/api/collections.html#Mongo-Collection-update)
115 |
116 | | Param | Type | Description |
117 | | --- | --- | --- |
118 | | selector | [MongoQuerySelector
](#Collection..MongoQuerySelector) | Specifies which documents to modify |
119 | | modifier | Modifier
| Specifies how to modify the documents |
120 | | options | MongoUpdateOptions
| Update options first argument and, if no error, the number of affected documents as the second |
121 |
122 |
123 |
124 | ### collection.upsert(selector, modifier, options) ⇒ Observable.<{numberAffected, insertedId}>
125 | Finds the first document that matches the selector, as ordered by sort and skip options.
126 |
127 | **Kind**: instance method of [Collection
](#Collection)
128 | **Returns**: Observable.<{numberAffected, insertedId}>
- Observable which completes with an
129 | Object that contain the keys numberAffected and insertedId.
130 | **See**: [upsert on Meteor documentation](https://docs.meteor.com/api/collections.html#Mongo-Collection-upsert)
131 |
132 | | Param | Type | Description |
133 | | --- | --- | --- |
134 | | selector | [MongoQuerySelector
](#Collection..MongoQuerySelector) | Specifies which documents to modify |
135 | | modifier | Modifier
| Specifies how to modify the documents |
136 | | options | MongoUpsertOptions
| Upsert options first argument and, if no error, the number of affected documents as the second. |
137 |
138 |
139 |
140 | ### collection.find(selector, options) ⇒ ObservableCursor.<T>
141 | Method has the same notation as Mongo.Collection.find, only returns Observable.
142 |
143 | **Kind**: instance method of [Collection
](#Collection)
144 | **Returns**: ObservableCursor.<T>
- RxJS Observable wrapped with Meteor features.
145 | **See**: [find on Meteor documentation](https://docs.meteor.com/api/collections.html#Mongo-Collection-find)
146 |
147 | | Param | Type | Description |
148 | | --- | --- | --- |
149 | | selector | [MongoQuerySelector
](#Collection..MongoQuerySelector) | A query describing the documents to find |
150 | | options | [MongoQueryOptions
](#Collection..MongoQueryOptions) | Query options, such as sort, limit, etc. |
151 |
152 | **Example** *(Using Angular2 Component)*
153 | ```js
154 | const MyCollection = MongoObservable.Collection("myCollection");
155 |
156 | class MyComponent {
157 | private myData: ObservableCursor;
158 |
159 | constructor() {
160 | this.myData = MyCollection.find({}, {limit: 10});
161 | }
162 | }
163 | ```
164 |
165 |
166 | ### collection.findOne(selector, options) ⇒ any
167 | Finds the first document that matches the selector, as ordered by sort and skip options.
168 |
169 | **Kind**: instance method of [Collection
](#Collection)
170 | **Returns**: any
- The first object, or `undefined` in case of non-existing object.
171 | **See**: [findOne on Meteor documentation](https://docs.meteor.com/api/collections.html#Mongo-Collection-findOne)
172 |
173 | | Param | Type | Description |
174 | | --- | --- | --- |
175 | | selector | [MongoQuerySelector
](#Collection..MongoQuerySelector) | A query describing the documents to find |
176 | | options | [MongoQueryOptions
](#Collection..MongoQueryOptions) | Query options, such as sort, limit, etc. |
177 |
178 |
179 |
180 | ### Collection~MongoQueryOptions : Object
181 | An options object for MongoDB queries.
182 |
183 | **Kind**: inner typedef of [Collection
](#Collection)
184 | **Properties**
185 |
186 | | Name | Type | Description |
187 | | --- | --- | --- |
188 | | sort | Object
| Sort order (default: natural order) |
189 | | skip | Number
| Number of results to skip at the beginning |
190 | | fields | Object
| Dictionary of fields to return or exclude. |
191 | | reactive | Boolean
| (Client only) Default true; pass false to disable reactivity |
192 | | transform | function
| Overrides transform on the Collection for this cursor. Pass null to disable transformation. |
193 |
194 |
195 |
196 | ### Collection~MongoQuerySelector : Mongo.Selector
\| Mongo.ObjectID
\| string
197 | A MongoDB query selector representation.
198 |
199 | **Kind**: inner typedef of [Collection
](#Collection)
200 |
201 |
202 | ### Collection~MongoUpsertOptions : Object
203 | A MongoDB query options for upsert action
204 |
205 | **Kind**: inner typedef of [Collection
](#Collection)
206 | **Properties**
207 |
208 | | Name | Type | Description |
209 | | --- | --- | --- |
210 | | multi | Boolean
| True to modify all matching documents; false to only modify one of the matching documents (the default). |
211 |
212 |
213 |
214 | ### Collection~MongoUpdateOptions : Object
215 | A MongoDB query options for update action
216 |
217 | **Kind**: inner typedef of [Collection
](#Collection)
218 | **Properties**
219 |
220 | | Name | Type | Description |
221 | | --- | --- | --- |
222 | | multi | Boolean
| True to modify all matching documents; |
223 | | upsert | Boolean
| True to use upsert logic. |
224 |
225 |
--------------------------------------------------------------------------------
/docs/ObservableCursor.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## ObservableCursor ⇐ Observable
4 | **Kind**: global class
5 | **Extends**: Observable
6 |
7 | * [ObservableCursor](#ObservableCursor) ⇐ Observable
8 | * [new ObservableCursor(cursor)](#new_ObservableCursor_new)
9 | * _instance_
10 | * [.cursor](#ObservableCursor+cursor) ⇒ Mongo.Cursor.<T>
11 | * [.collectionCount()](#ObservableCursor+collectionCount) ⇒ Observable
12 | * [.stop()](#ObservableCursor+stop)
13 | * [.dispose()](#ObservableCursor+dispose)
14 | * [.fetch()](#ObservableCursor+fetch) ⇒ Array.<T>
15 | * [.observe(callbacks)](#ObservableCursor+observe) ⇒ Meteor.LiveQueryHandle
16 | * [.observeChanges(callbacks)](#ObservableCursor+observeChanges) ⇒ Meteor.LiveQueryHandle
17 | * _static_
18 | * [.create(cursor)](#ObservableCursor.create) ⇒ [ObservableCursor
](#ObservableCursor)
19 |
20 |
21 |
22 | ### new ObservableCursor(cursor)
23 |
24 | | Param | Type | Description |
25 | | --- | --- | --- |
26 | | cursor | Mongo.Cursor.<T>
| The Mongo.Cursor to wrap. |
27 |
28 |
29 |
30 | ### observableCursor.cursor ⇒ Mongo.Cursor.<T>
31 | Returns the actual Mongo.Cursor that wrapped by current ObservableCursor instance.
32 |
33 | **Kind**: instance property of [ObservableCursor
](#ObservableCursor)
34 | **Returns**: Mongo.Cursor.<T>
- The actual MongoDB Cursor.
35 |
36 |
37 | ### observableCursor.collectionCount() ⇒ Observable
38 | A wrapper for Mongo.Cursor.count() method - returns an Observable of number, which
39 | triggers each time there is a change in the collection, and exposes the number of
40 | objects in the collection.
41 |
42 | **Kind**: instance method of [ObservableCursor
](#ObservableCursor)
43 | **Returns**: Observable
- Observable which trigger the callback when the
44 | count of the object changes.
45 |
46 |
47 | ### observableCursor.stop()
48 | Stops the observation on the cursor.
49 |
50 | **Kind**: instance method of [ObservableCursor
](#ObservableCursor)
51 |
52 |
53 | ### observableCursor.dispose()
54 | Clears the Observable definition.
55 | Use this method only when the Observable is still cold, and there are no active subscriptions yet.
56 |
57 | **Kind**: instance method of [ObservableCursor
](#ObservableCursor)
58 |
59 |
60 | ### observableCursor.fetch() ⇒ Array.<T>
61 | Return all matching documents as an Array.
62 |
63 | **Kind**: instance method of [ObservableCursor
](#ObservableCursor)
64 | **Returns**: Array.<T>
- The array with the matching documents.
65 |
66 |
67 | ### observableCursor.observe(callbacks) ⇒ Meteor.LiveQueryHandle
68 | Watch a query. Receive callbacks as the result set changes.
69 |
70 | **Kind**: instance method of [ObservableCursor
](#ObservableCursor)
71 | **Returns**: Meteor.LiveQueryHandle
- The array with the matching documents.
72 |
73 | | Param | Type | Description |
74 | | --- | --- | --- |
75 | | callbacks | Mongo.ObserveCallbacks
| The callbacks object. |
76 |
77 |
78 |
79 | ### observableCursor.observeChanges(callbacks) ⇒ Meteor.LiveQueryHandle
80 | Watch a query. Receive callbacks as the result set changes.
81 | Only the differences between the old and new documents are passed to the callbacks.
82 |
83 | **Kind**: instance method of [ObservableCursor
](#ObservableCursor)
84 | **Returns**: Meteor.LiveQueryHandle
- The array with the matching documents.
85 |
86 | | Param | Type | Description |
87 | | --- | --- | --- |
88 | | callbacks | Mongo.ObserveChangesCallbacks
| The callbacks object. |
89 |
90 |
91 |
92 | ### ObservableCursor.create(cursor) ⇒ [ObservableCursor
](#ObservableCursor)
93 | Static method which creates an ObservableCursor from Mongo.Cursor.
94 | Use this to create an ObservableCursor object from an existing Mongo.Cursor.
95 | Prefer to create an Cursors from the ObservableCollection instance instead.
96 |
97 | **Kind**: static method of [ObservableCursor
](#ObservableCursor)
98 | **Returns**: [ObservableCursor
](#ObservableCursor) - Wrapped Cursor.
99 |
100 | | Param | Type | Description |
101 | | --- | --- | --- |
102 | | cursor | Mongo.Cursor.<T>
| The Mongo.Cursor to wrap. |
103 |
104 |
--------------------------------------------------------------------------------
/examples/angular2/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .meteor/local
3 | npm-debug.log
4 | typings
5 | .idea
6 | .meteor/local
7 |
--------------------------------------------------------------------------------
/examples/angular2/.meteor/.finished-upgraders:
--------------------------------------------------------------------------------
1 | # This file contains information which helps Meteor properly upgrade your
2 | # app when you run 'meteor update'. You should check it into version control
3 | # with your project.
4 |
5 | notices-for-0.9.0
6 | notices-for-0.9.1
7 | 0.9.4-platform-file
8 | notices-for-facebook-graph-api-2
9 | 1.2.0-standard-minifiers-package
10 | 1.2.0-meteor-platform-split
11 | 1.2.0-cordova-changes
12 | 1.2.0-breaking-changes
13 | 1.3.0-split-minifiers-package
14 | 1.3.5-remove-old-dev-bundle-link
15 | 1.4.0-remove-old-dev-bundle-link
16 | 1.4.1-add-shell-server-package
17 |
--------------------------------------------------------------------------------
/examples/angular2/.meteor/.gitignore:
--------------------------------------------------------------------------------
1 | dev_bundle
2 | local
3 |
--------------------------------------------------------------------------------
/examples/angular2/.meteor/.id:
--------------------------------------------------------------------------------
1 | # This file contains a token that is unique to your project.
2 | # Check it into your repository along with the rest of this directory.
3 | # It can be used for purposes such as:
4 | # - ensuring you don't accidentally deploy one app on top of another
5 | # - providing package authors with aggregated statistics
6 |
7 | a4kqps1d5y31214lew0l
8 |
--------------------------------------------------------------------------------
/examples/angular2/.meteor/packages:
--------------------------------------------------------------------------------
1 | # Meteor packages used by this project, one per line.
2 | # Check this file (and the other files in this directory) into your repository.
3 | #
4 | # 'meteor add' and 'meteor remove' will edit this file for you,
5 | # but you can also edit it by hand.
6 |
7 | meteor-base@1.0.4 # Packages every Meteor app needs to have
8 | mobile-experience@1.0.4 # Packages for a great mobile UX
9 | mongo@1.1.14 # The database Meteor supports right now
10 | reactive-var@1.0.11 # Reactive variable for tracker
11 | tracker@1.1.1 # Meteor's client-side reactive programming library
12 |
13 | standard-minifier-css@1.3.2 # CSS minifier run for production mode
14 | standard-minifier-js@1.2.1 # JS minifier run for production mode
15 | es5-shim@4.6.15 # ECMAScript 5 compatibility for older browsers.
16 |
17 | autopublish@1.0.7 # Publish all data to the clients (for prototyping)
18 | insecure@1.0.7 # Allow all DB writes from clients (for prototyping)
19 | angular2-compilers
20 | practicalmeteor:mocha
21 | xolvio:cleaner
22 | hwillson:stub-collections
23 | dispatch:mocha-phantomjs
24 | shell-server@0.2.1
25 |
--------------------------------------------------------------------------------
/examples/angular2/.meteor/platforms:
--------------------------------------------------------------------------------
1 | server
2 | browser
3 |
--------------------------------------------------------------------------------
/examples/angular2/.meteor/release:
--------------------------------------------------------------------------------
1 | METEOR@1.4.2
2 |
--------------------------------------------------------------------------------
/examples/angular2/.meteor/versions:
--------------------------------------------------------------------------------
1 | allow-deny@1.0.5
2 | angular2-compilers@0.6.5
3 | autopublish@1.0.7
4 | autoupdate@1.3.12
5 | babel-compiler@6.13.0
6 | babel-runtime@0.1.13
7 | barbatus:css-compiler@0.3.4
8 | barbatus:scss-compiler@3.8.2
9 | barbatus:typescript@0.5.2
10 | barbatus:typescript-compiler@0.8.4
11 | barbatus:typescript-runtime@0.1.2
12 | base64@1.0.10
13 | binary-heap@1.0.10
14 | blaze@2.2.0
15 | blaze-tools@1.0.10
16 | boilerplate-generator@1.0.11
17 | caching-compiler@1.1.8
18 | caching-html-compiler@1.0.7
19 | callback-hook@1.0.10
20 | check@1.2.4
21 | coffeescript@1.11.1_2
22 | ddp@1.2.5
23 | ddp-client@1.3.2
24 | ddp-common@1.2.7
25 | ddp-server@1.3.11
26 | deps@1.0.12
27 | diff-sequence@1.0.7
28 | dispatch:mocha-phantomjs@0.1.7
29 | dispatch:phantomjs-tests@0.0.5
30 | ecmascript@0.5.9
31 | ecmascript-runtime@0.3.15
32 | ejson@1.0.13
33 | es5-shim@4.6.15
34 | fastclick@1.0.13
35 | geojson-utils@1.0.10
36 | hot-code-push@1.0.4
37 | html-tools@1.0.11
38 | htmljs@1.0.11
39 | http@1.2.10
40 | hwillson:stub-collections@1.0.2
41 | id-map@1.0.9
42 | insecure@1.0.7
43 | jquery@1.11.10
44 | launch-screen@1.1.0
45 | livedata@1.0.18
46 | logging@1.1.16
47 | meteor@1.6.0
48 | meteor-base@1.0.4
49 | minifier-css@1.2.15
50 | minifier-js@1.2.15
51 | minimongo@1.0.18
52 | mobile-experience@1.0.4
53 | mobile-status-bar@1.0.13
54 | modules@0.7.7
55 | modules-runtime@0.7.7
56 | mongo@1.1.14
57 | mongo-id@1.0.6
58 | npm-mongo@2.2.11_2
59 | observe-sequence@1.0.14
60 | ordered-dict@1.0.9
61 | practicalmeteor:chai@2.1.0_1
62 | practicalmeteor:loglevel@1.2.0_2
63 | practicalmeteor:mocha@2.4.5_6
64 | practicalmeteor:mocha-core@1.0.1
65 | practicalmeteor:sinon@1.14.1_2
66 | promise@0.8.8
67 | random@1.0.10
68 | reactive-var@1.0.11
69 | reload@1.1.11
70 | retry@1.0.9
71 | routepolicy@1.0.12
72 | shell-server@0.2.1
73 | spacebars@1.0.13
74 | spacebars-compiler@1.0.13
75 | standard-minifier-css@1.3.2
76 | standard-minifier-js@1.2.1
77 | templating@1.2.15
78 | templating-compiler@1.2.15
79 | templating-runtime@1.2.15
80 | templating-tools@1.0.5
81 | tmeasday:test-reporter-helpers@0.2.1
82 | tracker@1.1.1
83 | ui@1.0.12
84 | underscore@1.0.10
85 | urigo:static-html-compiler@0.1.8
86 | url@1.0.11
87 | webapp@1.3.12
88 | webapp-hashing@1.0.9
89 | xolvio:cleaner@0.3.1
90 |
--------------------------------------------------------------------------------
/examples/angular2/both/collections/demo.collection.ts:
--------------------------------------------------------------------------------
1 | import { MongoObservable } from "meteor-rxjs";
2 | import {Demo} from "../models/demo.model";
3 |
4 | export const DemoCollection = new MongoObservable.Collection("demo-collection");
5 |
--------------------------------------------------------------------------------
/examples/angular2/both/models/demo.model.ts:
--------------------------------------------------------------------------------
1 | export interface Demo {
2 | name: string;
3 | age: number;
4 | }
5 |
--------------------------------------------------------------------------------
/examples/angular2/client/imports/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
Angular 2 with Meteor-RxJS Example
3 |
4 | Items:
5 |
6 | -
7 | {{ item._id }}
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/examples/angular2/client/imports/app/app.component.scss:
--------------------------------------------------------------------------------
1 | app {
2 |
3 | }
--------------------------------------------------------------------------------
/examples/angular2/client/imports/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, ChangeDetectionStrategy} from "@angular/core";
2 | import template from "./app.component.html";
3 | import style from "./app.component.scss";
4 | import {MeteorObservable} from "../../../../../src/MeteorObservable";
5 | import {DemoCollection} from "../../../both/collections/demo.collection";
6 |
7 | @Component({
8 | selector: "app",
9 | template,
10 | styles: [ style ],
11 | changeDetection: ChangeDetectionStrategy.OnPush
12 | })
13 | export class AppComponent {
14 | items = DemoCollection.find({});
15 |
16 | constructor() {
17 | }
18 | }
--------------------------------------------------------------------------------
/examples/angular2/client/imports/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from "@angular/core";
2 | import { BrowserModule } from "@angular/platform-browser";
3 | import { AppComponent } from "./app.component";
4 |
5 | @NgModule({
6 | // Components, Pipes, Directive
7 | declarations: [
8 | AppComponent
9 | ],
10 | // Entry Components
11 | entryComponents: [
12 | AppComponent
13 | ],
14 | // Providers
15 | providers: [
16 |
17 | ],
18 | // Modules
19 | imports: [
20 | BrowserModule
21 | ],
22 | // Main Component
23 | bootstrap: [ AppComponent ]
24 | })
25 | export class AppModule {
26 | constructor() {
27 |
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/examples/angular2/client/imports/app/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./app.component";
2 | export * from "./app.module";
3 |
--------------------------------------------------------------------------------
/examples/angular2/client/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Loading...
6 |
7 |
--------------------------------------------------------------------------------
/examples/angular2/client/main.ts:
--------------------------------------------------------------------------------
1 | import "angular2-meteor-polyfills";
2 |
3 | import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
4 | import { enableProdMode } from "@angular/core";
5 | import { Meteor } from "meteor/meteor";
6 | import { AppModule } from "./imports/app";
7 |
8 | enableProdMode();
9 |
10 | Meteor.startup(() => {
11 | platformBrowserDynamic().bootstrapModule(AppModule);
12 | });
13 |
--------------------------------------------------------------------------------
/examples/angular2/client/styles/main.scss:
--------------------------------------------------------------------------------
1 | body, html {
2 |
3 | }
--------------------------------------------------------------------------------
/examples/angular2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular2-meteor-rxjs-example",
3 | "private": true,
4 | "scripts": {
5 | "start": "meteor run",
6 | "start:prod": "meteor run --production",
7 | "build": "meteor build ./build/",
8 | "clear": "meteor reset",
9 | "meteor:update": "meteor update --all-packages",
10 | "test": "meteor test --driver-package practicalmeteor:mocha",
11 | "test:ci": "meteor test --once --driver-package dispatch:mocha-phantomjs"
12 | },
13 | "devDependencies": {
14 | "@types/chai": "^3.4.33",
15 | "@types/mocha": "^2.2.32",
16 | "chai": "3.5.0",
17 | "chai-spies": "0.7.1"
18 | },
19 | "dependencies": {
20 | "@angular/common": "2.1.2",
21 | "@angular/compiler": "2.1.2",
22 | "@angular/core": "2.1.2",
23 | "@angular/forms": "2.1.2",
24 | "@angular/platform-browser": "2.1.2",
25 | "@angular/platform-browser-dynamic": "2.1.2",
26 | "@angular/router": "3.1.2",
27 | "@types/meteor": "1.3.31",
28 | "angular2-meteor": "0.7.0",
29 | "angular2-meteor-polyfills": "0.1.1",
30 | "angular2-meteor-tests-polyfills": "0.0.2",
31 | "meteor-node-stubs": "0.2.3",
32 | "meteor-rxjs": "../../",
33 | "reflect-metadata": "0.1.8",
34 | "rxjs": "5.0.0-beta.12",
35 | "zone.js": "0.6.26"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/examples/angular2/server/imports/server-main/main.ts:
--------------------------------------------------------------------------------
1 | import {DemoCollection} from "../../../both/collections/demo.collection";
2 | import {Demo} from "../../../both/models/demo.model";
3 |
4 | export class Main {
5 | start(): void {
6 | this.initFakeData();
7 | }
8 |
9 | initFakeData(): void {
10 | if (DemoCollection.find({}).cursor.count() === 0) {
11 | const data: Demo[] = [{
12 | name: "Dotan",
13 | age: 25
14 | }, {
15 | name: "Liran",
16 | age: 26
17 | }, {
18 | name: "Uri",
19 | age: 30
20 | }];
21 | data.forEach((obj: Demo) => {
22 | DemoCollection.insert(obj);
23 | });
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/examples/angular2/server/main.ts:
--------------------------------------------------------------------------------
1 | import { Main } from "./imports/server-main/main";
2 |
3 | const mainInstance = new Main();
4 | mainInstance.start();
5 |
--------------------------------------------------------------------------------
/examples/angular2/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "es6",
6 | "dom"
7 | ],
8 | "module": "commonjs",
9 | "moduleResolution": "node",
10 | "experimentalDecorators": true,
11 | "emitDecoratorMetadata": true,
12 | "sourceMap": true
13 | },
14 | "exclude": [
15 | "node_modules"
16 | ],
17 | "files": [
18 | "typings.d.ts"
19 | ],
20 | "compileOnSave": false,
21 | "angularCompilerOptions": {
22 | "genDir": "aot",
23 | "skipMetadataEmit": true
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/examples/angular2/typings.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | ///
4 |
5 | declare module "*.html" {
6 | const template: string;
7 | export default template;
8 | }
9 |
10 | declare module "*.scss" {
11 | const style: string;
12 | export default style;
13 | }
14 |
15 | declare module "*.less" {
16 | const style: string;
17 | export default style;
18 | }
19 |
20 | declare module "*.css" {
21 | const style: string;
22 | export default style;
23 | }
24 |
25 | declare module "*.sass" {
26 | const style: string;
27 | export default style;
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/generate-docs.sh:
--------------------------------------------------------------------------------
1 | rm -rf temp &> /dev/null
2 | mkdir temp &> /dev/null
3 | tsc --outDir ./temp/ --target es6
4 | $(npm bin)/jsdoc2md -l js --no-cache --source "$(cat ./temp/MeteorObservable.js)" > ./docs/MeteorObservable.md
5 | $(npm bin)/jsdoc2md -l js --no-cache --source "$(cat ./temp/ObservableCollection.js)" > ./docs/ObservableCollection.md
6 | $(npm bin)/jsdoc2md -l js --no-cache --source "$(cat ./temp/ObservableCursor.js)" > ./docs/ObservableCursor.md
7 | rm -rf temp &> /dev/null
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "meteor-rxjs",
3 | "version": "0.4.11",
4 | "description": "Use Meteor API in RxJS style",
5 | "keywords": [
6 | "rxjs",
7 | "angular",
8 | "angular2",
9 | "meteor",
10 | "mongo",
11 | "typescript"
12 | ],
13 | "main": "dist/bundles/index.umd.js",
14 | "module": "dist/index.js",
15 | "typings": "dist/index.d.ts",
16 | "scripts": {
17 | "changelog": "$(npm bin)/conventional-changelog -p meteor-rxjs -i CHANGELOG.md -s -r 0",
18 | "docs": "./generate-docs.sh",
19 | "prebuild": "npm run lint",
20 | "build": "npm run build-only && npm run bundle && npm run docs",
21 | "prepublish": "npm run build",
22 | "build-only": "tsc || echo not ok",
23 | "pretest": "cd tests && rm -rf node_modules && npm install",
24 | "test-ci": "npm run pretest && cd tests && meteor test --once --driver-package dispatch:mocha-phantomjs",
25 | "test": "cd tests && meteor test --driver-package practicalmeteor:mocha",
26 | "lint": "tslint src/**/*.ts",
27 | "bundle": "rollup -i ./dist/index.js -o ./dist/bundles/index.umd.js -n meteor.rxjs -c rollup.config.js"
28 | },
29 | "repository": {
30 | "type": "git",
31 | "url": "git+https://github.com/Urigo/mongo-rxjs-observable.git"
32 | },
33 | "author": "Angular2-Meteor (https://github.com/Urigo/angular2-meteor)",
34 | "license": "MIT",
35 | "bugs": {
36 | "url": "https://github.com/Urigo/mongo-rxjs-observable/issues"
37 | },
38 | "homepage": "http://www.angular-meteor.com",
39 | "peerDependencies": {
40 | "@types/meteor": "^1.4.6",
41 | "rxjs": "^5.4.3 || ^6.0.0"
42 | },
43 | "devDependencies": {
44 | "@types/chai": "4.0.4",
45 | "@types/meteor": "1.4.14",
46 | "@types/mocha": "2.2.43",
47 | "@types/underscore": "1.8.3",
48 | "conventional-changelog": "1.1.0",
49 | "conventional-changelog-cli": "1.2.0",
50 | "jsdoc-to-markdown": "3.0.0",
51 | "rollup": "1.10.0",
52 | "rxjs": "6.0.0",
53 | "rxjs-compat": "6.0.0",
54 | "tslint": "5.7.0",
55 | "typescript": "2.7.2",
56 | "zone.js": "0.8.20"
57 | },
58 | "greenkeeper": {
59 | "ignore": [
60 | "rxjs"
61 | ]
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | output: {
3 | format: 'umd'
4 | },
5 | globals: {
6 | 'rxjs': 'rxjs'
7 | }
8 | };
9 |
--------------------------------------------------------------------------------
/src/MeteorObservable.ts:
--------------------------------------------------------------------------------
1 | import { Observable , Subscriber } from 'rxjs';
2 |
3 | import { isMeteorCallbacks, forkZone, removeObserver } from './utils';
4 |
5 | let liveSubscriptions = [];
6 |
7 | function throwInvalidCallback(method: string) {
8 | throw new Error(
9 | `Invalid ${method} arguments:
10 | your last param can't be a callback function,
11 | please remove it and use ".subscribe" of the Observable!`);
12 | }
13 |
14 | /**
15 | * This is a class with static methods that wrap Meteor's API and return RxJS
16 | * Observables. The methods' signatures are the same as Meteor's, with the ]
17 | * exception that the callbacks are handled by Meteor-rxjs. Instead of
18 | * providing callbacks, you need to subscribe to the observables that are
19 | * returned. The methods that are wrapped in MeteorObservable are
20 | * [Meteor.call](https://docs.meteor.com/api/methods.html#Meteor-call),
21 | * [Meteor.autorun](https://docs.meteor.com/api/tracker.html#Tracker-autorun)
22 | * and [Meteor.subscribe](https://docs.meteor.com/api/pubsub.html#Meteor-subscribe).
23 | */
24 | export class MeteorObservable {
25 |
26 | /**
27 | * Invokes a [Meteor Method](https://docs.meteor.com/api/methods.html)
28 | * defined on the server, passing any number of arguments. This method has
29 | * the same signature as
30 | * [Meteor.call](https://docs.meteor.com/api/methods.html#Meteor-call), only
31 | * without the callbacks:
32 | * MeteorObservable.call(name, [...args])
33 | *
34 | *
35 | * @param {string} name - Name of the method in the Meteor server
36 | * @param {any} args - Parameters that will be forwarded to the method.
37 | * after the func call to initiate change detection.
38 | * @returns {Observable} - RxJS Observable, which completes when the
39 | * server returns a response.
40 | *
41 | * @example Example using Angular2 Component
42 | * class MyComponent {
43 | * constructor() {
44 | *
45 | * }
46 | *
47 | * doAction(payload) {
48 | * MeteorObservable.call("myData", payload).subscribe((response) => {
49 | * // Handle success and response from server!
50 | * }, (err) => {
51 | * // Handle error
52 | * });
53 | * }
54 | * }
55 | */
56 | public static call(name: string, ...args: any[]): Observable {
57 | const lastParam = args[args.length - 1];
58 |
59 | if (isMeteorCallbacks(lastParam)) {
60 | throwInvalidCallback('MeteorObservable.call');
61 | }
62 |
63 | let zone = forkZone();
64 |
65 | return Observable.create((observer: Subscriber) => {
66 | Meteor.call(name, ...args.concat([
67 | (error: Meteor.Error, result: T) => {
68 | zone.run(() => {
69 | error ? observer.error(error) :
70 | observer.next(result);
71 | observer.complete();
72 | });
73 | }
74 | ]));
75 | });
76 | }
77 |
78 | /**
79 | * When you subscribe to a collection, it tells the server to send records to
80 | * the client. This method has the same signature as
81 | * [Meteor.subscribe](https://docs.meteor.com/api/pubsub.html#Meteor-subscribe),
82 | * except without the callbacks again:
83 | * subscribe(name, [...args])
84 | *
85 | * You can use this method from any Angular2 element - such as Component,
86 | * Pipe or Service.
87 | *
88 | * @param {string} name - Name of the publication in the Meteor server
89 | * @param {any} args - Parameters that will be forwarded to the publication.
90 | * after the func call to initiate change detection.
91 | * @returns {Observable} - RxJS Observable, which completes when the
92 | * subscription is ready.
93 | *
94 | * @example Example using Angular2 Service
95 | * class MyService {
96 | * private meteorSubscription: Observable;
97 | *
98 | * constructor() {
99 | *
100 | * }
101 | *
102 | * subscribeToData() {
103 | * this.meteorSubscription = MeteorObservable.subscribe("myData").subscribe(() => {
104 | * // Subscription is ready!
105 | * });
106 | * }
107 | *
108 | * unsubscribeToData() {
109 | * this.meteorSubscription.unsubscribe();
110 | * }
111 | * }
112 | *
113 | * @example Example using Angular2 Component
114 | * class MyComponent implements OnInit, OnDestroy {
115 | * private meteorSubscription: Observable;
116 | *
117 | * constructor() {
118 | *
119 | * }
120 | *
121 | * ngOnInit() {
122 | * this.meteorSubscription = MeteorObservable.subscribe("myData").subscribe(() => {
123 | * // Subscription is ready!
124 | * });
125 | * }
126 | *
127 | * ngOnDestroy() {
128 | * this.meteorSubscription.unsubscribe();
129 | * }
130 | * }
131 | *
132 | * @see {@link http://docs.meteor.com/api/pubsub.html|Publications in Meteor documentation}
133 | */
134 | public static subscribe(name: string, ...args: any[]): Observable {
135 | let lastParam = args[args.length - 1];
136 |
137 | if (isMeteorCallbacks(lastParam)) {
138 | throwInvalidCallback('MeteorObservable.subscribe');
139 | }
140 |
141 | let zone = forkZone();
142 | let observers = [];
143 | let subscribe = () => {
144 | return Meteor.subscribe(name, ...args.concat([{
145 | onError: (error: Meteor.Error) => {
146 | zone.run(() => {
147 | observers.forEach(observer => observer.error(error));
148 | });
149 | },
150 | onReady: () => {
151 | zone.run(() => {
152 | observers.forEach(observer => observer.next());
153 | });
154 | }
155 | }
156 | ]));
157 | };
158 |
159 | let subHandler = null;
160 | return Observable.create((observer: Subscriber) => {
161 | observers.push(observer);
162 | // Execute subscribe lazily.
163 | if (subHandler === null) {
164 | subHandler = subscribe();
165 | if (liveSubscriptions.find(sub => sub === subHandler.subscriptionId)) {
166 | // subscription already exists, call observer.next() since Meteor won't.
167 | observer.next();
168 | } else {
169 | liveSubscriptions.push(subHandler.subscriptionId);
170 | }
171 | }
172 | return () => {
173 | removeObserver(observers,
174 | observer, () => {
175 | // remove subscription from liveSubscriptions list
176 | let i = liveSubscriptions.findIndex(
177 | sub => sub === subHandler.subscriptionId
178 | );
179 |
180 | if (i > -1) {
181 | liveSubscriptions.splice(i, 1);
182 | }
183 |
184 | subHandler.stop();
185 |
186 | });
187 | };
188 | });
189 | }
190 |
191 | /**
192 | * Allows you to run a function every time there is a change is a reactive
193 | * data sources. This method has the same signature as
194 | * [Meteor.autorun](https://docs.meteor.com/api/tracker.html#Tracker-autorun),
195 | * only without the callback:
196 | * MeteorObservable.autorun()
197 | *
198 | * @returns {Observable} - RxJS Observable, which trigger the subscription callback
199 | * each time that Meteor Tracker detects a change.
200 | * @example Example using Angular2 Component
201 | * class MyComponent {
202 | * constructor() {
203 | *
204 | * }
205 | *
206 | * doAction(payload) {
207 | * MeteorObservable.autorun().subscribe(() => {
208 | * // Handle Tracker autorun change
209 | * });
210 | * }
211 | * }
212 | */
213 | public static autorun(): Observable {
214 | let zone = forkZone();
215 | let observers = [];
216 | let autorun = () => {
217 | return Tracker.autorun((computation: Tracker.Computation) => {
218 | zone.run(() => {
219 | observers.forEach(observer => observer.next(computation));
220 | });
221 | });
222 | };
223 |
224 | let handler = null;
225 | return Observable.create((observer: Subscriber) => {
226 | observers.push(observer);
227 | // Execute autorun lazily.
228 | if (handler === null) {
229 | handler = autorun();
230 | }
231 | return () => {
232 | removeObserver(observers,
233 | observer, () => handler.stop());
234 | };
235 | });
236 | }
237 | }
238 |
--------------------------------------------------------------------------------
/src/ObservableCollection.ts:
--------------------------------------------------------------------------------
1 | import { Observable , Subscriber } from 'rxjs';
2 |
3 | import { ObservableCursor } from './ObservableCursor';
4 | import { removeObserver } from './utils';
5 |
6 | import Selector = Mongo.Selector;
7 | import ObjectID = Mongo.ObjectID;
8 | import SortSpecifier = Mongo.SortSpecifier;
9 | import FieldSpecifier = Mongo.FieldSpecifier;
10 | import Modifier = Mongo.Modifier;
11 |
12 | export module MongoObservable {
13 | 'use strict';
14 |
15 | export interface ConstructorOptions {
16 | connection?: Object;
17 | idGeneration?: string;
18 | transform?: Function;
19 | }
20 |
21 | export interface AllowDenyOptionsObject {
22 | insert?: (userId: string, doc: T) => boolean;
23 | update?: (userId: string, doc: T, fieldNames: string[], modifier: any) => boolean;
24 | remove?: (userId: string, doc: T) => boolean;
25 | fetch?: string[];
26 | transform?: Function;
27 | }
28 |
29 | /**
30 | * Creates a new MongoObservable.Collection from an existing of predefined Mongo.Collection.
31 | * Use this feature to wrap existing collections such as Meteor.users.
32 | * @param {Mongo.Collection} collection - The collection.
33 | * @returns {MongoObservable.Collection} - Wrapped collection.
34 | * @static
35 | */
36 | export function fromExisting(collection: Mongo.Collection): MongoObservable.Collection {
37 | return new MongoObservable.Collection(collection);
38 | }
39 |
40 | /**
41 | * A class represents a MongoDB collection in the client side, wrapped with RxJS
42 | * Observables, so you can use it with your Angular 2 easier.
43 | * The wrapper has the same API as Mongo.Collection, only the "find" method returns
44 | * an ObservableCursor instead of regular Mongo.Cursor.
45 | *
46 | * T is a generic type - should be used with the type of the objects inside the collection.
47 | */
48 | export class Collection {
49 | private _collection: Mongo.Collection;
50 |
51 | /**
52 | * Creates a new Mongo.Collection instance wrapped with Observable features.
53 | * @param {String | Mongo.Collection} nameOrExisting - The name of the collection. If null, creates an
54 | * unmanaged (unsynchronized) local collection. If provided an instance of existing collection, will
55 | * create a wrapper for the existing Mongo.Collection.
56 | * @param {ConstructorOptions} options - Creation options.
57 | * @constructor
58 | */
59 | constructor(nameOrExisting: string | Mongo.Collection,
60 | options?: ConstructorOptions) {
61 | if (nameOrExisting instanceof Mongo.Collection) {
62 | this._collection = nameOrExisting;
63 | } else {
64 | this._collection = new Mongo.Collection(nameOrExisting, options);
65 | }
66 | }
67 |
68 | /**
69 | * Returns the Mongo.Collection object that wrapped with the MongoObservable.Collection.
70 | * @returns {Mongo.Collection} The Collection instance
71 | */
72 | get collection(): Mongo.Collection {
73 | return this._collection;
74 | }
75 |
76 | /**
77 | * Allow users to write directly to this collection from client code, subject to limitations you define.
78 | *
79 | * @returns {Boolean}
80 | */
81 | allow(options: AllowDenyOptionsObject): boolean {
82 | return this._collection.allow(options);
83 | }
84 |
85 | /**
86 | * Override allow rules.
87 | *
88 | * @returns {Boolean}
89 | */
90 | deny(options: AllowDenyOptionsObject): boolean {
91 | return this._collection.deny(options);
92 | }
93 |
94 | /**
95 | * Returns the Collection object corresponding to this collection from the npm
96 | * mongodb driver module which is wrapped by Mongo.Collection.
97 | *
98 | * @returns {Mongo.Collection} The Collection instance
99 | *
100 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-rawCollection|rawCollection on Meteor documentation}
101 | */
102 | rawCollection(): any {
103 | return this._collection.rawCollection();
104 | }
105 |
106 | /**
107 | * Returns the Db object corresponding to this collection's database connection from the
108 | * npm mongodb driver module which is wrapped by Mongo.Collection.
109 | *
110 | * @returns {Mongo.Db} The Db instance
111 | *
112 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-rawDatabase|rawDatabase on Meteor documentation}
113 | */
114 | rawDatabase(): any {
115 | return this._collection.rawDatabase();
116 | }
117 |
118 | /**
119 | * Insert a document in the collection.
120 | *
121 | * @param {T} doc - The document to insert. May not yet have an _id
122 | * attribute, in which case Meteor will generate one for you.
123 | * @returns {Observable} Observable which completes with the inserted ObjectId
124 | *
125 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-insert|insert on Meteor documentation}
126 | */
127 | insert(doc: T): Observable {
128 | let observers: Subscriber[] = [];
129 | let obs = this._createObservable(observers);
130 |
131 | this._collection.insert(doc,
132 | (error: Meteor.Error, docId: string) => {
133 | observers.forEach(observer => {
134 | error ? observer.error(error) :
135 | observer.next(docId);
136 | observer.complete();
137 | });
138 | });
139 | return obs;
140 | }
141 |
142 | /**
143 | * Remove documents from the collection.
144 | *
145 | * @param {Collection~MongoQuerySelector} selector - Specifies which documents to modify
146 | * @returns {Observable} Observable which completes with the number of affected rows
147 | *
148 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-remove|remove on Meteor documentation}
149 | */
150 | remove(selector: Selector | ObjectID | string): Observable {
151 | let observers: Subscriber[] = [];
152 | let obs = this._createObservable(observers);
153 |
154 | this._collection.remove(selector,
155 | (error: Meteor.Error, removed: number) => {
156 | observers.forEach(observer => {
157 | error ? observer.error(error) :
158 | observer.next(removed);
159 | observer.complete();
160 | });
161 | });
162 |
163 | return obs;
164 | }
165 |
166 | /**
167 | * Modify one or more documents in the collection.
168 | *
169 | * @param {Collection~MongoQuerySelector} selector - Specifies which documents to modify
170 | * @param {Modifier} modifier - Specifies how to modify the documents
171 | * @param {MongoUpdateOptions} options - Update options
172 | * first argument and, if no error, the number of affected documents as the second
173 | * @returns {Observable} Observable which completes with the number of affected rows
174 | *
175 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-update|update on Meteor documentation}
176 | */
177 | update(selector: Selector | ObjectID | string,
178 | modifier: Modifier,
179 | options?: { multi?: boolean; upsert?: boolean; }): Observable {
180 | let observers: Subscriber[] = [];
181 | let obs = this._createObservable(observers);
182 |
183 | this._collection.update(selector, modifier, options,
184 | (error: Meteor.Error, updated: number) => {
185 | observers.forEach(observer => {
186 | error ? observer.error(error) :
187 | observer.next(updated);
188 | observer.complete();
189 | });
190 | });
191 |
192 | return obs;
193 | }
194 |
195 | /**
196 | * Finds the first document that matches the selector, as ordered by sort and skip options.
197 | *
198 | * @param {Collection~MongoQuerySelector} selector - Specifies which documents to modify
199 | * @param {Modifier} modifier - Specifies how to modify the documents
200 | * @param {MongoUpsertOptions} options - Upsert options
201 | * first argument and, if no error, the number of affected documents as the second.
202 | * @returns {Observable<{numberAffected, insertedId}>} Observable which completes with an
203 | * Object that contain the keys numberAffected and insertedId.
204 | *
205 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-upsert|upsert on Meteor documentation}
206 | */
207 | upsert(selector: Selector | ObjectID | string,
208 | modifier: Modifier,
209 | options?: { multi?: boolean; }): Observable {
210 | let observers: Subscriber[] = [];
211 | let obs = this._createObservable(observers);
212 |
213 | this._collection.upsert(selector, modifier, options,
214 | (error: Meteor.Error, affected: number) => {
215 | observers.forEach(observer => {
216 | error ? observer.error(error) :
217 | observer.next(affected);
218 | observer.complete();
219 | });
220 | });
221 |
222 | return obs;
223 | }
224 |
225 | /**
226 | * Method has the same notation as Mongo.Collection.find, only returns Observable.
227 | *
228 | * @param {Collection~MongoQuerySelector} selector - A query describing the documents to find
229 | * @param {Collection~MongoQueryOptions} options - Query options, such as sort, limit, etc.
230 | * @returns {ObservableCursor} RxJS Observable wrapped with Meteor features.
231 | * @example Using Angular2 Component
232 | * const MyCollection = MongoObservable.Collection("myCollection");
233 | *
234 | * class MyComponent {
235 | * private myData: ObservableCursor;
236 | *
237 | * constructor() {
238 | * this.myData = MyCollection.find({}, {limit: 10});
239 | * }
240 | * }
241 | *
242 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-find|find on Meteor documentation}
243 | */
244 | find(selector?: Selector | ObjectID | string, options?: {
245 | sort?: SortSpecifier;
246 | skip?: number;
247 | limit?: number;
248 | fields?: FieldSpecifier;
249 | reactive?: boolean;
250 | transform?: Function;
251 | }): ObservableCursor {
252 | const cursor = this._collection.find.apply(
253 | this._collection, arguments);
254 | return ObservableCursor.create(cursor);
255 | }
256 |
257 | /**
258 | * Finds the first document that matches the selector, as ordered by sort and skip options.
259 | *
260 | * @param {Collection~MongoQuerySelector} selector - A query describing the documents to find
261 | * @param {Collection~MongoQueryOptions} options - Query options, such as sort, limit, etc.
262 | * @returns {any} The first object, or `undefined` in case of non-existing object.
263 | *
264 | * @see {@link https://docs.meteor.com/api/collections.html#Mongo-Collection-findOne|findOne on Meteor documentation}
265 | */
266 | findOne(selector?: Selector | ObjectID | string, options?: {
267 | sort?: SortSpecifier;
268 | skip?: number;
269 | fields?: FieldSpecifier;
270 | reactive?: boolean;
271 | transform?: Function;
272 | }): T {
273 | return this._collection.findOne.apply(
274 | this._collection, arguments);
275 | }
276 |
277 | private _createObservable(observers: Subscriber[]) {
278 | return Observable.create((observer: Subscriber) => {
279 | observers.push(observer);
280 | return () => {
281 | removeObserver(observers, observer);
282 | };
283 | });
284 | }
285 | }
286 | }
287 |
288 |
289 | /**
290 | * An options object for MongoDB queries.
291 | * @typedef {Object} Collection~MongoQueryOptions
292 | * @property {Object} sort - Sort order (default: natural order)
293 | * @property {Number} skip - Number of results to skip at the beginning
294 | * @property {Object} fields - Dictionary of fields to return or exclude.
295 | * @property {Boolean} reactive - (Client only) Default true; pass false to disable reactivity
296 | * @property {Function} transform - Overrides transform on the Collection for this cursor. Pass null to disable transformation.
297 | */
298 |
299 | /**
300 | * A MongoDB query selector representation.
301 | * @typedef {(Mongo.Selector|Mongo.ObjectID|string)} Collection~MongoQuerySelector
302 | */
303 |
304 | /**
305 | * A MongoDB query options for upsert action
306 | * @typedef {Object} Collection~MongoUpsertOptions
307 | * @property {Boolean} multi - True to modify all matching documents;
308 | * false to only modify one of the matching documents (the default).
309 | */
310 |
311 | /**
312 | * A MongoDB query options for update action
313 | * @typedef {Object} Collection~MongoUpdateOptions
314 | * @property {Boolean} multi - True to modify all matching documents;
315 | * @property {Boolean} upsert - True to use upsert logic.
316 | */
317 |
--------------------------------------------------------------------------------
/src/ObservableCursor.ts:
--------------------------------------------------------------------------------
1 | import { Observable , Subscriber , Subject } from 'rxjs';
2 |
3 | import { gZone, forkZone, removeObserver } from './utils';
4 |
5 | declare let _;
6 |
7 | export class ObservableCursor extends Observable {
8 | private _zone: Zone;
9 | private _data: Array = [];
10 | private _cursor: Mongo.Cursor;
11 | private _hCursor: Meteor.LiveQueryHandle;
12 | private _observers: Subscriber[] = [];
13 | private _countObserver: Subject = new Subject();
14 | private _isDataInitinialized = false;
15 |
16 | /**
17 | * Static method which creates an ObservableCursor from Mongo.Cursor.
18 | * Use this to create an ObservableCursor object from an existing Mongo.Cursor.
19 | * Prefer to create an Cursors from the ObservableCollection instance instead.
20 | *
21 | * @param {Mongo.Cursor} cursor - The Mongo.Cursor to wrap.
22 | * @static
23 | * @returns {ObservableCursor} Wrapped Cursor.
24 | */
25 | static create(cursor: Mongo.Cursor): ObservableCursor {
26 | return new ObservableCursor(cursor);
27 | }
28 |
29 | /**
30 | * @constructor
31 | * @extends Observable
32 | * @param {Mongo.Cursor} cursor - The Mongo.Cursor to wrap.
33 | */
34 | constructor(cursor: Mongo.Cursor) {
35 | super((observer: Subscriber) => {
36 | this._observers.push(observer);
37 |
38 | if (!this._hCursor) {
39 | this._hCursor = this._observeCursor(cursor);
40 | }
41 |
42 | Meteor.setTimeout(() => {
43 | if (this._isDataInitinialized) {
44 | observer.next(this._data);
45 | } else if (cursor.count() === 0) {
46 | this._isDataInitinialized = true;
47 | observer.next(this._data);
48 | }
49 | }, 0);
50 |
51 | return () => {
52 | removeObserver(this._observers,
53 | observer, () => this.stop());
54 | };
55 | });
56 |
57 | _.extend(this, _.omit(cursor, 'count', 'map'));
58 |
59 | this._cursor = cursor;
60 | this._zone = forkZone();
61 | }
62 |
63 | /**
64 | * Returns the actual Mongo.Cursor that wrapped by current ObservableCursor instance.
65 | * @return {Mongo.Cursor} The actual MongoDB Cursor.
66 | */
67 | get cursor(): Mongo.Cursor {
68 | return this._cursor;
69 | }
70 |
71 | /**
72 | * A wrapper for Mongo.Cursor.count() method - returns an Observable of number, which
73 | * triggers each time there is a change in the collection, and exposes the number of
74 | * objects in the collection.
75 | * @returns {Observable} Observable which trigger the callback when the
76 | * count of the object changes.
77 | */
78 | collectionCount(): Observable {
79 | return this._countObserver.asObservable();
80 | }
81 |
82 | /**
83 | * Stops the observation on the cursor.
84 | */
85 | stop() {
86 | this._zone.run(() => {
87 | this._runComplete();
88 | });
89 |
90 | if (this._hCursor) {
91 | this._hCursor.stop();
92 | }
93 |
94 | this._data = [];
95 | this._hCursor = null;
96 | }
97 |
98 | /**
99 | * Clears the Observable definition.
100 | * Use this method only when the Observable is still cold, and there are no active subscriptions yet.
101 | */
102 | dispose() {
103 | this._observers = null;
104 | this._cursor = null;
105 | }
106 |
107 | /**
108 | * Return all matching documents as an Array.
109 | *
110 | * @return {Array} The array with the matching documents.
111 | */
112 | fetch(): Array {
113 | return this._cursor.fetch();
114 | }
115 |
116 | /**
117 | * Watch a query. Receive callbacks as the result set changes.
118 | * @param {Mongo.ObserveCallbacks} callbacks - The callbacks object.
119 | * @return {Meteor.LiveQueryHandle} The array with the matching documents.
120 | */
121 | observe(callbacks: Object): Meteor.LiveQueryHandle {
122 | return this._cursor.observe(callbacks);
123 | }
124 |
125 | /**
126 | * Watch a query. Receive callbacks as the result set changes.
127 | * Only the differences between the old and new documents are passed to the callbacks.
128 | * @param {Mongo.ObserveChangesCallbacks} callbacks - The callbacks object.
129 | * @return {Meteor.LiveQueryHandle} The array with the matching documents.
130 | */
131 | observeChanges(callbacks: Object): Meteor.LiveQueryHandle {
132 | return this._cursor.observeChanges(callbacks);
133 | }
134 |
135 | _runComplete() {
136 | this._countObserver.complete();
137 |
138 | this._observers.forEach(observer => {
139 | observer.complete();
140 | });
141 | }
142 |
143 | _runNext(data: Array) {
144 | this._countObserver.next(this._data.length);
145 |
146 | this._observers.forEach(observer => {
147 | observer.next(data);
148 | });
149 | }
150 |
151 | _addedAt(doc, at, before) {
152 | this._data.splice(at, 0, doc);
153 | this._handleChange();
154 | }
155 |
156 | _changedAt(doc, old, at) {
157 | this._data[at] = doc;
158 | this._handleChange();
159 | }
160 |
161 | _removedAt(doc, at) {
162 | this._data.splice(at, 1);
163 | this._handleChange();
164 | }
165 |
166 | _movedTo(doc, fromIndex, toIndex) {
167 | this._data.splice(fromIndex, 1);
168 | this._data.splice(toIndex, 0, doc);
169 | this._handleChange();
170 | }
171 |
172 | _handleChange() {
173 | this._isDataInitinialized = true;
174 |
175 | this._zone.run(() => {
176 | this._runNext(this._data);
177 | });
178 | }
179 |
180 | _observeCursor(cursor: Mongo.Cursor) {
181 | return gZone.run(
182 | () => cursor.observe({
183 | addedAt: this._addedAt.bind(this),
184 | changedAt: this._changedAt.bind(this),
185 | movedTo: this._movedTo.bind(this),
186 | removedAt: this._removedAt.bind(this)
187 | }));
188 | }
189 | }
190 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './ObservableCollection';
2 | export * from './MeteorObservable';
3 | export * from './ObservableCursor';
4 | export * from './zone';
5 |
--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------
1 | import { Subscriber } from 'rxjs';
2 |
3 | declare let _;
4 |
5 | export declare type CallbacksObject = {
6 | onReady?: Function;
7 | onError?: Function;
8 | onStop?: Function;
9 | };
10 |
11 | export declare type MeteorCallbacks = ((...args) => any) | CallbacksObject;
12 |
13 | export const subscribeEvents = ['onReady', 'onError', 'onStop'];
14 |
15 | export function isMeteorCallbacks(callbacks: any): boolean {
16 | return _.isFunction(callbacks) || isCallbacksObject(callbacks);
17 | }
18 |
19 | // Checks if callbacks of {@link CallbacksObject} type.
20 | export function isCallbacksObject(callbacks: any): boolean {
21 | return callbacks && subscribeEvents.some((event) => {
22 | return _.isFunction(callbacks[event]);
23 | });
24 | }
25 |
26 | declare const global;
27 | export const g =
28 | typeof global === 'object' ? global :
29 | typeof window === 'object' ? window :
30 | typeof self === 'object' ? self : undefined;
31 |
32 | const METEOR_RXJS_ZONE = 'meteor-rxjs-zone';
33 |
34 | const fakeZone = {
35 | name: METEOR_RXJS_ZONE,
36 | run(func: Function) {
37 | return func();
38 | },
39 | fork(spec: any) {
40 | return fakeZone;
41 | }
42 | };
43 |
44 | export function forkZone() {
45 | if (g.Zone) {
46 | let zone = g.Zone.current;
47 | if (zone.name === METEOR_RXJS_ZONE) {
48 | zone = zone.parent || fakeZone;
49 | }
50 | return zone.fork({ name: METEOR_RXJS_ZONE });
51 | }
52 | return fakeZone;
53 | }
54 |
55 | export function getZone() {
56 | if (g.Zone) {
57 | let zone = g.Zone.current;
58 | if (zone.name === METEOR_RXJS_ZONE) {
59 | return zone.parent;
60 | }
61 | return zone;
62 | }
63 | }
64 |
65 | export function removeObserver(observers: Subscriber[],
66 | observer: Subscriber,
67 | onEmpty?: Function) {
68 | let index = observers.indexOf(observer);
69 | observers.splice(index, 1);
70 | if (observers.length === 0 && onEmpty) {
71 | onEmpty();
72 | }
73 | }
74 |
75 | export const gZone = g.Zone ? g.Zone.current : fakeZone;
76 |
--------------------------------------------------------------------------------
/src/zone.ts:
--------------------------------------------------------------------------------
1 | import { Observable , Operator , Subscriber } from 'rxjs';
2 |
3 | import { getZone } from './utils';
4 |
5 | export const zoneOperator = (zone?: Zone) => (source: Observable) => source.lift(new ZoneOperator(zone || getZone()));
6 |
7 |
8 | class ZoneOperator implements Operator {
9 | constructor(private zone: Zone) {
10 | }
11 |
12 | call(subscriber: Subscriber, source: any) {
13 | return source._subscribe(new ZoneSubscriber(subscriber, this.zone));
14 | }
15 | }
16 |
17 | class ZoneSubscriber extends Subscriber {
18 | constructor(destination: Subscriber,
19 | private zone: Zone) {
20 | super(destination);
21 | }
22 |
23 | protected _next(value: T) {
24 | this.zone.run(() => {
25 | this.destination.next(value);
26 | });
27 | }
28 |
29 | protected _complete() {
30 | this.zone.run(() => {
31 | this.destination.complete();
32 | });
33 | }
34 |
35 | protected _error(err?: any) {
36 | this.zone.run(() => {
37 | this.destination.error(err);
38 | });
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/tests/.meteor/.finished-upgraders:
--------------------------------------------------------------------------------
1 | # This file contains information which helps Meteor properly upgrade your
2 | # app when you run 'meteor update'. You should check it into version control
3 | # with your project.
4 |
5 | notices-for-0.9.0
6 | notices-for-0.9.1
7 | 0.9.4-platform-file
8 | notices-for-facebook-graph-api-2
9 | 1.2.0-standard-minifiers-package
10 | 1.2.0-meteor-platform-split
11 | 1.2.0-cordova-changes
12 | 1.2.0-breaking-changes
13 | 1.3.0-split-minifiers-package
14 | 1.4.0-remove-old-dev-bundle-link
15 | 1.4.1-add-shell-server-package
16 | 1.4.3-split-account-service-packages
17 | 1.5-add-dynamic-import-package
18 |
--------------------------------------------------------------------------------
/tests/.meteor/.gitignore:
--------------------------------------------------------------------------------
1 | local
2 |
--------------------------------------------------------------------------------
/tests/.meteor/.id:
--------------------------------------------------------------------------------
1 | # This file contains a token that is unique to your project.
2 | # Check it into your repository along with the rest of this directory.
3 | # It can be used for purposes such as:
4 | # - ensuring you don't accidentally deploy one app on top of another
5 | # - providing package authors with aggregated statistics
6 |
7 | 1bh2ud7roqxsj1ibpje
8 |
--------------------------------------------------------------------------------
/tests/.meteor/packages:
--------------------------------------------------------------------------------
1 | # Meteor packages used by this project, one per line.
2 | # Check this file (and the other files in this directory) into your repository.
3 | #
4 | # 'meteor add' and 'meteor remove' will edit this file for you,
5 | # but you can also edit it by hand.
6 |
7 | meteor-base@1.1.0 # Packages every Meteor app needs to have
8 | mobile-experience@1.0.4 # Packages for a great mobile UX
9 | mongo@1.2.0 # The database Meteor supports right now
10 | reactive-var@1.0.11 # Reactive variable for tracker
11 | jquery@1.11.10 # Helpful client-side library
12 | tracker@1.1.3 # Meteor's client-side reactive programming library
13 |
14 | standard-minifier-css@1.3.4 # CSS minifier run for production mode
15 | standard-minifier-js@2.1.1 # JS minifier run for production mode
16 | es5-shim@4.6.15 # ECMAScript 5 compatibility for older browsers.
17 | ecmascript@0.8.2 # Enable ECMAScript2015+ syntax in app code
18 |
19 | insecure@1.0.7 # Allow all DB writes from clients (for prototyping)
20 | angular2-compilers
21 | practicalmeteor:sinon
22 | practicalmeteor:chai
23 | dispatch:mocha-phantomjs
24 | dburles:factory
25 | xolvio:cleaner
26 | shell-server@0.2.4
27 | practicalmeteor:mocha
28 | dynamic-import
29 |
--------------------------------------------------------------------------------
/tests/.meteor/platforms:
--------------------------------------------------------------------------------
1 | server
2 | browser
3 |
--------------------------------------------------------------------------------
/tests/.meteor/release:
--------------------------------------------------------------------------------
1 | METEOR@1.5.2
2 |
--------------------------------------------------------------------------------
/tests/.meteor/versions:
--------------------------------------------------------------------------------
1 | allow-deny@1.0.6
2 | angular2-compilers@0.6.6
3 | autoupdate@1.3.12
4 | babel-compiler@6.20.0
5 | babel-runtime@1.0.1
6 | barbatus:caching-compiler@1.1.9
7 | barbatus:css-compiler@0.4.1
8 | barbatus:scss-compiler@3.8.3
9 | barbatus:typescript@0.6.11
10 | barbatus:typescript-compiler@0.9.11
11 | barbatus:typescript-runtime@1.0.2
12 | base64@1.0.10
13 | binary-heap@1.0.10
14 | blaze@2.3.2
15 | blaze-tools@1.0.10
16 | boilerplate-generator@1.2.0
17 | caching-compiler@1.1.9
18 | caching-html-compiler@1.1.2
19 | callback-hook@1.0.10
20 | check@1.2.5
21 | coffeescript@1.12.7_1
22 | coffeescript-compiler@1.12.7_1
23 | dburles:factory@1.1.0
24 | ddp@1.3.0
25 | ddp-client@2.1.0
26 | ddp-common@1.2.9
27 | ddp-server@2.0.0
28 | deps@1.0.12
29 | diff-sequence@1.0.7
30 | dispatch:mocha-phantomjs@0.1.9
31 | dispatch:phantomjs-tests@0.0.7
32 | dynamic-import@0.1.1
33 | ecmascript@0.8.2
34 | ecmascript-runtime@0.4.1
35 | ecmascript-runtime-client@0.4.3
36 | ecmascript-runtime-server@0.4.1
37 | ejson@1.0.14
38 | es5-shim@4.6.15
39 | fastclick@1.0.13
40 | geojson-utils@1.0.10
41 | hot-code-push@1.0.4
42 | html-tools@1.0.11
43 | htmljs@1.0.11
44 | http@1.2.12
45 | id-map@1.0.9
46 | insecure@1.0.7
47 | jquery@1.11.10
48 | launch-screen@1.1.1
49 | livedata@1.0.18
50 | logging@1.1.17
51 | meteor@1.7.1
52 | meteor-base@1.1.0
53 | minifier-css@1.2.16
54 | minifier-js@2.1.3
55 | minimongo@1.3.0
56 | mobile-experience@1.0.4
57 | mobile-status-bar@1.0.14
58 | modules@0.10.0
59 | modules-runtime@0.8.0
60 | mongo@1.2.0
61 | mongo-dev-server@1.0.1
62 | mongo-id@1.0.6
63 | npm-mongo@2.2.30
64 | observe-sequence@1.0.16
65 | ordered-dict@1.0.9
66 | practicalmeteor:chai@2.1.0_1
67 | practicalmeteor:loglevel@1.2.0_2
68 | practicalmeteor:mocha@2.4.5_6
69 | practicalmeteor:mocha-core@1.0.1
70 | practicalmeteor:sinon@1.14.1_2
71 | promise@0.9.0
72 | random@1.0.10
73 | reactive-var@1.0.11
74 | reload@1.1.11
75 | retry@1.0.9
76 | routepolicy@1.0.12
77 | shell-server@0.2.4
78 | spacebars@1.0.15
79 | spacebars-compiler@1.1.3
80 | standard-minifier-css@1.3.4
81 | standard-minifier-js@2.1.1
82 | templating@1.3.2
83 | templating-compiler@1.3.2
84 | templating-runtime@1.3.2
85 | templating-tools@1.1.2
86 | tmeasday:test-reporter-helpers@0.2.1
87 | tracker@1.1.3
88 | underscore@1.0.10
89 | urigo:static-html-compiler@0.1.8
90 | url@1.1.0
91 | webapp@1.3.18
92 | webapp-hashing@1.0.9
93 | xolvio:cleaner@0.3.1
94 |
--------------------------------------------------------------------------------
/tests/client/unit/meteor-observable.spec.ts:
--------------------------------------------------------------------------------
1 | import {chai} from 'meteor/practicalmeteor:chai';
2 | import {sinon} from 'meteor/practicalmeteor:sinon';
3 | import {MeteorObservable} from 'meteor-rxjs';
4 | import {Observable} from 'rxjs';
5 |
6 | const expect = chai.expect;
7 |
8 | describe('MeteorObservable', () => {
9 | describe('call', () => {
10 | it('Should return RxJS Observable when using "call"', () => {
11 | let returnValue = MeteorObservable.call('testMethod');
12 | expect(returnValue instanceof Observable).to.equal(true);
13 | });
14 |
15 | it('Should NOT run the actual "call" method without subscribing to the result', () => {
16 | let spy = sinon.spy(Meteor, 'call');
17 | MeteorObservable.call('testMethod');
18 | expect(spy.called).to.equal(false);
19 | spy.restore();
20 | });
21 |
22 | it('Should run the actual "call" method when subscribing to the result', () => {
23 | let spy = sinon.spy(Meteor, 'call');
24 | let subHandler = MeteorObservable.call('testMethod').subscribe();
25 | expect(spy.calledOnce).to.equal(true);
26 | spy.restore();
27 | subHandler.unsubscribe();
28 | });
29 |
30 | it('Should trigger the RxJS Observable "next" callback when got the server response',
31 | (done) => {
32 | let subHandler = MeteorObservable.call('testMethod').subscribe((serverResponse) => {
33 | expect(serverResponse).to.equal('TEST_VALUE');
34 | subHandler.unsubscribe();
35 | done();
36 | });
37 | });
38 |
39 | it('Should trigger the RxJS Observable "error" callback when got the server error',
40 | (done) => {
41 | let subscriptionHandler = MeteorObservable.call('NON_EXISTING_METHOD').subscribe(null,
42 | (e) => {
43 | expect(e instanceof Meteor.Error).to.equal(true);
44 | subscriptionHandler.unsubscribe();
45 | done();
46 | });
47 | });
48 | });
49 |
50 | describe('subscribe', () => {
51 | function getSubsCount() {
52 | return Object.keys((Meteor).default_connection._subscriptions).length;
53 | }
54 |
55 | it('Should return RxJS Observable when using "subscribe"', () => {
56 | let returnValue = MeteorObservable.subscribe('test');
57 | expect(returnValue instanceof Observable).to.equal(true);
58 | });
59 |
60 | it('Should NOT run the actual "subscribe" method without subscribing to the result', () => {
61 | let spy = sinon.spy(Meteor, 'subscribe');
62 | MeteorObservable.subscribe('test');
63 | expect(spy.called).to.equal(false);
64 | spy.restore();
65 | });
66 |
67 | it('Should run the actual "subscribe" method when subscribing to the result', () => {
68 | let spy = sinon.spy(Meteor, 'subscribe');
69 | let subHandler = MeteorObservable.subscribe('test').subscribe();
70 | expect(spy.called).to.equal(true);
71 | spy.restore();
72 | subHandler.unsubscribe();
73 | });
74 |
75 | it('Should call RxJS Observable "next" callback when subscription is ready', done => {
76 | let subHandler = MeteorObservable.subscribe('test').subscribe(() => {
77 | subHandler.unsubscribe();
78 | done();
79 | });
80 | });
81 |
82 | it('Should stop subscription when one observer subscribes', done => {
83 | let baseCount = getSubsCount();
84 | let subHandler = MeteorObservable.subscribe('test').subscribe(() => {
85 | expect(getSubsCount()).to.equal(baseCount + 1);
86 | subHandler.unsubscribe();
87 | expect(getSubsCount()).to.equal(baseCount);
88 | done();
89 | });
90 | });
91 |
92 | it('Should persist same subscription when two observers subscribe, and then one unsubscribes',
93 | done => {
94 | let baseCount = getSubsCount();
95 | let observable = MeteorObservable.subscribe('test');
96 | let subHandler1 = observable.subscribe(() => {});
97 | let subHandler2 = observable.subscribe(() => {
98 | expect(getSubsCount()).to.equal(baseCount + 1);
99 | subHandler1.unsubscribe();
100 | expect(getSubsCount()).to.equal(baseCount + 1);
101 | subHandler2.unsubscribe();
102 | expect(getSubsCount()).to.equal(baseCount);
103 | done();
104 | });
105 | });
106 | });
107 | });
108 |
--------------------------------------------------------------------------------
/tests/client/unit/observable-collection.spec.ts:
--------------------------------------------------------------------------------
1 | import {chai} from 'meteor/practicalmeteor:chai';
2 | import {sinon} from 'meteor/practicalmeteor:sinon';
3 | import {MongoObservable, ObservableCursor} from 'meteor-rxjs';
4 | import {Observable} from 'rxjs';
5 |
6 | const expect = chai.expect;
7 |
8 | describe('MongoObservable methods bridge', () => {
9 | let observable = new MongoObservable.Collection(null);
10 | let mongoCollection = observable.collection;
11 |
12 | it('Should return RxJS Observable object when using "find"', () => {
13 | let findResult = observable.find({});
14 | expect(findResult instanceof Observable).to.equal(true);
15 | });
16 |
17 | it('Should wrap existing collection', () => {
18 | let collection = new Mongo.Collection(null);
19 | let insert = sinon.stub(collection, 'insert');
20 |
21 | let observable = new MongoObservable.Collection(collection);
22 | observable.insert({});
23 | expect(insert.calledOnce).to.be.true;
24 | });
25 |
26 | it('Insert should return an observable', done => {
27 | observable.insert({}).subscribe(id => {
28 | expect(id).to.be.string;
29 | done();
30 | });
31 | });
32 |
33 | it('Remove should return an observable', done => {
34 | observable.insert({}).subscribe(id => {
35 | observable.remove(id).subscribe(() => {
36 | done();
37 | });
38 | });
39 | });
40 |
41 | function testOriginalMethod(methodName) {
42 | it(`Should call the original ${methodName} method of the Mongo.Collection`, () => {
43 | let stub = sinon.stub(mongoCollection, methodName);
44 | observable[methodName]({});
45 | expect(stub.calledOnce).to.equal(true);
46 | });
47 | }
48 |
49 | testOriginalMethod('allow');
50 | testOriginalMethod('deny');
51 | testOriginalMethod('insert');
52 | testOriginalMethod('rawCollection');
53 | testOriginalMethod('rawDatabase');
54 | testOriginalMethod('remove');
55 | testOriginalMethod('update');
56 | testOriginalMethod('upsert');
57 | testOriginalMethod('find');
58 | testOriginalMethod('findOne');
59 | });
60 |
--------------------------------------------------------------------------------
/tests/client/unit/observable-cursor.spec.ts:
--------------------------------------------------------------------------------
1 | import {chai} from 'meteor/practicalmeteor:chai';
2 | import {sinon} from 'meteor/practicalmeteor:sinon';
3 | import {Observable} from 'rxjs';
4 | import {ObservableCursor, MongoObservable} from 'meteor-rxjs';
5 |
6 |
7 |
8 |
9 | const expect = chai.expect;
10 |
11 | describe('ObservableCursor', function () {
12 | let collection: Mongo.Collection;
13 | let cursor: Mongo.Cursor;
14 | let observable: ObservableCursor;
15 |
16 | beforeEach(function () {
17 | collection = new Mongo.Collection(null);
18 | collection.allow({
19 | insert: function () {
20 | return true;
21 | },
22 | remove: function () {
23 | return true;
24 | },
25 | update: function () {
26 | return true;
27 | }
28 | });
29 |
30 | cursor = collection.find({});
31 | observable = ObservableCursor.create(cursor);
32 | });
33 |
34 | it('Should wrap the Mongo.Cursor and return RxJS Observable', () => {
35 | expect(observable instanceof Observable).to.equal(true);
36 | });
37 |
38 | it('Should not use the actual Cursor "observeChanges" method w/o Observable subscription', () => {
39 | let spy = sinon.spy(cursor, 'observeChanges');
40 | expect(spy.called).to.equal(false);
41 | spy.restore();
42 | });
43 |
44 | it('Should use the actual Cursor "observeChanges" after using Observable subscription', () => {
45 | let spy = sinon.spy(cursor, 'observeChanges');
46 | let subHandler = observable.subscribe();
47 | expect(spy.calledOnce).to.equal(true);
48 | spy.restore();
49 | subHandler.unsubscribe();
50 | });
51 |
52 | it('Should not trigger subscription callback when creating the subscription', () => {
53 | let spy = sinon.spy();
54 | let subscriptionHandler = observable.subscribe(spy);
55 | expect(spy.called).to.equal(false);
56 | subscriptionHandler.unsubscribe();
57 | });
58 |
59 | it('Subscription should unsubscribe after the unsubscribe call', () => {
60 | let subHandler;
61 | let callback = () => {
62 | subHandler.unsubscribe();
63 | };
64 | let spy = sinon.spy(callback);
65 | subHandler = observable.subscribe(spy);
66 | collection.insert({});
67 | collection.insert({});
68 | expect(spy.calledOnce).to.be.true;
69 | });
70 |
71 | it('Should trigger subscription callback when adding data to the collection', () => {
72 | let newDoc = {name: 'newDoc'};
73 | let subHandler;
74 | let callback = docs => {
75 | let inserted = docs[0];
76 | expect(inserted.name).to.equal(newDoc.name);
77 | subHandler.unsubscribe();
78 | };
79 | let spy = sinon.spy(callback);
80 | subHandler = observable.subscribe(spy);
81 | collection.insert(newDoc);
82 | expect(spy.calledOnce).to.be.true;
83 | });
84 |
85 | it('Should trigger subscription callback when moving items in the collection', (done) => {
86 | cursor = collection.find({}, {sort: {name: 1}});
87 | observable = ObservableCursor.create(cursor);
88 |
89 | let newDoc = {name: 'ZZZZ'};
90 | let subHandler;
91 | let count = 0;
92 |
93 | let callback = docs => {
94 | count++;
95 |
96 | // 4 because: insert, insert, update, *move*
97 | console.log(count);
98 | if (count === 4) {
99 | let firstItem = docs[0];
100 | expect(firstItem.name).to.equal('AAAA');
101 | subHandler.unsubscribe();
102 | done();
103 | }
104 | };
105 |
106 | subHandler = observable.subscribe(callback);
107 |
108 | let objectId = collection.insert(newDoc);
109 |
110 | collection.insert({
111 | name: 'BBBB'
112 | });
113 |
114 | collection.update({_id: objectId}, { $set: {name: 'AAAA'} });
115 | });
116 |
117 | it('Should trigger callback twice when inserting a doc and then removing it', () => {
118 | let count = 0;
119 | let subHandler;
120 | let callback = docs => {
121 | count++;
122 | if (count == 2) {
123 | expect(docs.length).to.equal(0);
124 | subHandler.unsubscribe();
125 | }
126 | };
127 | let spy = sinon.spy(callback);
128 | let subHandler = observable.subscribe(spy);
129 | let idToRemove = collection.insert({test: true});
130 | collection.remove(idToRemove);
131 | expect(spy.calledTwice).to.be.true;
132 | });
133 |
134 | it('Should subscription callback should have updated docs after updating', done => {
135 | let count = 0;
136 | let callback = docs => {
137 | count++;
138 | if (count == 1) {
139 | expect(docs[0].test).to.equal(true);
140 | }
141 |
142 | if (count == 2) {
143 | expect(docs[0].test).to.equal(false);
144 | subHandler.unsubscribe();
145 | done();
146 | }
147 | };
148 | let spy = sinon.spy(callback);
149 |
150 | let subHandler = observable.subscribe(spy);
151 | let idToUpdate = collection.insert({test: true});
152 | collection.update({_id: idToUpdate}, {$set: {test: false}});
153 | expect(spy.calledTwice).to.be.true;
154 | });
155 |
156 | it('Should stop Mongo cursor when the last subscription unsubscribes', () => {
157 | let stopSpy = sinon.spy();
158 | let spy = sinon.stub(cursor, 'observeChanges', () => {
159 | return {
160 | stop: stopSpy
161 | }
162 | });
163 |
164 | let subHandler = observable.subscribe();
165 | subHandler.unsubscribe();
166 |
167 | expect(stopSpy.callCount).to.equal(1);
168 | spy.restore();
169 | });
170 |
171 | it('RxJS operators should persist', () => {
172 | expect(observable.count).to.equal(Observable.prototype.count);
173 | expect(observable.map).to.equal(Observable.prototype.map);
174 | });
175 |
176 | it('Should trigger collectionCount when adding item', () => {
177 | let newDoc = {name: 'newDoc'};
178 | let subHandler, subCountHandler;
179 | let callback = count => {
180 | expect(count).to.equal(1);
181 | subHandler.unsubscribe();
182 | subCountHandler.unsubscribe();
183 | };
184 |
185 | subHandler = observable.subscribe();
186 | subCountHandler = observable.collectionCount().subscribe(callback);
187 | collection.insert(newDoc);
188 | });
189 |
190 | it('Should trigger collectionCount when adding and removing items', (done) => {
191 | let newDoc = {name: 'newDoc'};
192 | let subHandler, subCountHandler;
193 | let c = 0;
194 |
195 | let callback = count => {
196 | if (c === 0) {
197 | expect(count).to.equal(1);
198 | }
199 | else if (c === 1) {
200 | expect(count).to.equal(0);
201 | subHandler.unsubscribe();
202 | subCountHandler.unsubscribe();
203 | done();
204 | }
205 |
206 | c++;
207 | };
208 |
209 | subHandler = observable.subscribe();
210 | subCountHandler = observable.collectionCount().subscribe(callback);
211 | let id = collection.insert(newDoc);
212 | collection.remove({_id: id});
213 | });
214 |
215 | it('Multiple subscription for the same Observable should replay last value', () => {
216 | let wrappedCollection = MongoObservable.fromExisting(collection);
217 | let observable = wrappedCollection.find({});
218 |
219 | let spyCb1 = sinon.spy();
220 | let spyCb2 = sinon.spy();
221 | let firstSubscriptionHandler = observable.subscribe(spyCb1);
222 | wrappedCollection.insert({test: 1});
223 | wrappedCollection.insert({test: 2});
224 | wrappedCollection.insert({test: 3});
225 | let secondSubscriptionHandler = observable.subscribe(spyCb2);
226 | wrappedCollection.insert({test: 4});
227 |
228 | expect(spyCb1.callCount).to.equal(4);
229 | expect(spyCb2.callCount).to.equal(1);
230 |
231 | firstSubscriptionHandler.unsubscribe();
232 | secondSubscriptionHandler.unsubscribe();
233 | });
234 | });
235 |
--------------------------------------------------------------------------------
/tests/client/unit/zone-operator.spec.ts:
--------------------------------------------------------------------------------
1 | import {chai} from 'meteor/practicalmeteor:chai';
2 | import {sinon} from 'meteor/practicalmeteor:sinon';
3 | import {Observable} from 'rxjs';
4 | import {MeteorObservable, MongoObservable,zoneOperator} from 'meteor-rxjs';
5 |
6 | import 'zone.js/dist/zone.js';
7 |
8 | const expect = chai.expect;
9 |
10 | describe('ZoneOperator', () => {
11 | let observable = new MongoObservable.Collection(null);
12 | observable.allow({
13 | insert: function () {
14 | return true;
15 | }
16 | });
17 |
18 | it('Should run in the expected zone on the next', done => {
19 | let gZone = Zone.current;
20 | let zone = Zone.current.fork({ name: 'ng'});
21 |
22 | let obs: Observable = Observable.create(observer => {
23 | gZone.run(() => observer.next());
24 | });
25 | zone.run(() => {
26 | obs.pipe(zoneOperator()).subscribe(() => {
27 | expect(Zone.current).to.equal(zone);
28 | done();
29 | });
30 | });
31 | });
32 |
33 | it('Zone operator should use propagated zone from the autorun observable',
34 | done => {
35 | let zone = Zone.current.fork({ name: 'ng'});
36 | zone.run(() => {
37 | let subHandler = MeteorObservable.autorun().subscribe(() => {
38 | console.log(subHandler);
39 | observable.find({}).pipe(zoneOperator()).subscribe(() => {
40 | expect(Zone.current).to.equal(zone);
41 | subHandler.unsubscribe();
42 | done();
43 | });
44 | });
45 | });
46 | observable.insert({});
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/tests/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tests",
3 | "private": true,
4 | "scripts": {
5 | "start": "meteor run"
6 | },
7 | "dependencies": {
8 | "babel-runtime": "^6.26.0",
9 | "es6-shim": "^0.35.3",
10 | "meteor-rxjs": "file:..",
11 | "rxjs": "^6.0.0",
12 | "rxjs-compat": "^6.0.0",
13 | "zone.js": "0.8.17",
14 | "@types/meteor": "^1.4.6"
15 | },
16 | "devDependencies": {
17 | "linklocal": "^2.8.1"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/tests/server/lib/create-test-method.spec.ts:
--------------------------------------------------------------------------------
1 | let collection = new Mongo.Collection('testCollectionServer');
2 |
3 | Meteor.methods({
4 | 'testMethod': function() {
5 | return 'TEST_VALUE';
6 | }
7 | });
8 |
9 | Meteor.publish('test', () => {
10 | return collection.find({});
11 | });
12 |
--------------------------------------------------------------------------------
/tests/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "diagnostics": false
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/tests/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | babel-runtime@6.26.0:
6 | version "6.26.0"
7 | resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
8 | dependencies:
9 | core-js "^2.4.0"
10 | regenerator-runtime "^0.11.0"
11 |
12 | balanced-match@^1.0.0:
13 | version "1.0.0"
14 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
15 |
16 | brace-expansion@^1.1.7:
17 | version "1.1.11"
18 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
19 | dependencies:
20 | balanced-match "^1.0.0"
21 | concat-map "0.0.1"
22 |
23 | commander@^2.11.0:
24 | version "2.15.0"
25 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.0.tgz#ad2a23a1c3b036e392469b8012cec6b33b4c1322"
26 |
27 | concat-map@0.0.1:
28 | version "0.0.1"
29 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
30 |
31 | core-js@^2.4.0:
32 | version "2.5.3"
33 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e"
34 |
35 | debug@^2.6.8:
36 | version "2.6.9"
37 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
38 | dependencies:
39 | ms "2.0.0"
40 |
41 | es6-shim@0.35.3:
42 | version "0.35.3"
43 | resolved "https://registry.yarnpkg.com/es6-shim/-/es6-shim-0.35.3.tgz#9bfb7363feffff87a6cdb6cd93e405ec3c4b6f26"
44 |
45 | fs.realpath@^1.0.0:
46 | version "1.0.0"
47 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
48 |
49 | glob@^7.0.5:
50 | version "7.1.2"
51 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
52 | dependencies:
53 | fs.realpath "^1.0.0"
54 | inflight "^1.0.4"
55 | inherits "2"
56 | minimatch "^3.0.4"
57 | once "^1.3.0"
58 | path-is-absolute "^1.0.0"
59 |
60 | inflight@^1.0.4:
61 | version "1.0.6"
62 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
63 | dependencies:
64 | once "^1.3.0"
65 | wrappy "1"
66 |
67 | inherits@2:
68 | version "2.0.3"
69 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
70 |
71 | linklocal@2.8.1:
72 | version "2.8.1"
73 | resolved "https://registry.yarnpkg.com/linklocal/-/linklocal-2.8.1.tgz#3db5a1767afaa127772bdc7a80cbae460dfa30a5"
74 | dependencies:
75 | commander "^2.11.0"
76 | debug "^2.6.8"
77 | map-limit "0.0.1"
78 | mkdirp "^0.5.1"
79 | rimraf "^2.6.1"
80 |
81 | map-limit@0.0.1:
82 | version "0.0.1"
83 | resolved "https://registry.yarnpkg.com/map-limit/-/map-limit-0.0.1.tgz#eb7961031c0f0e8d001bf2d56fab685d58822f38"
84 | dependencies:
85 | once "~1.3.0"
86 |
87 | "meteor-rxjs@file:..":
88 | version "0.4.8"
89 |
90 | minimatch@^3.0.4:
91 | version "3.0.4"
92 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
93 | dependencies:
94 | brace-expansion "^1.1.7"
95 |
96 | minimist@0.0.8:
97 | version "0.0.8"
98 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
99 |
100 | mkdirp@^0.5.1:
101 | version "0.5.1"
102 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
103 | dependencies:
104 | minimist "0.0.8"
105 |
106 | ms@2.0.0:
107 | version "2.0.0"
108 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
109 |
110 | once@^1.3.0:
111 | version "1.4.0"
112 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
113 | dependencies:
114 | wrappy "1"
115 |
116 | once@~1.3.0:
117 | version "1.3.3"
118 | resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20"
119 | dependencies:
120 | wrappy "1"
121 |
122 | path-is-absolute@^1.0.0:
123 | version "1.0.1"
124 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
125 |
126 | regenerator-runtime@^0.11.0:
127 | version "0.11.1"
128 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
129 |
130 | rimraf@^2.6.1:
131 | version "2.6.2"
132 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
133 | dependencies:
134 | glob "^7.0.5"
135 |
136 | rxjs@5.4.3:
137 | version "5.4.3"
138 | resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.4.3.tgz#0758cddee6033d68e0fd53676f0f3596ce3d483f"
139 | dependencies:
140 | symbol-observable "^1.0.1"
141 |
142 | symbol-observable@^1.0.1:
143 | version "1.2.0"
144 | resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
145 |
146 | wrappy@1:
147 | version "1.0.2"
148 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
149 |
150 | zone.js@0.8.17:
151 | version "0.8.17"
152 | resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.8.17.tgz#4c5e5185a857da8da793daf3919371c5a36b2a0b"
153 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "experimentalDecorators": true,
4 | "module": "es2015",
5 | "target": "es5",
6 | "lib": ["es2015", "dom"],
7 | "noImplicitAny": false,
8 | "suppressImplicitAnyIndexErrors": true,
9 | "moduleResolution": "node",
10 | "emitDecoratorMetadata": true,
11 | "sourceMap": true,
12 | "declaration": true,
13 | "outDir": "./dist",
14 | "rootDir": "./src",
15 | "types": [
16 | "zone.js",
17 | "@types/chai",
18 | "@types/meteor",
19 | "@types/underscore"
20 | ]
21 | },
22 | "files": [
23 | "src/index.ts"
24 | ],
25 | "exclude": [
26 | "node_modules"
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "align": [true, "parameters"],
4 | "class-name": true,
5 | "curly": true,
6 | "eofline": true,
7 | "forin": true,
8 | "indent": [true, "spaces"],
9 | "label-position": true,
10 | "max-line-length": [true, 150],
11 | "member-access": false,
12 | "member-ordering": [true,
13 | "public-before-private",
14 | "static-before-instance",
15 | "variables-before-functions"
16 | ],
17 | "no-arg": true,
18 | "no-bitwise": true,
19 | "no-console": [true,
20 | "debug",
21 | "info",
22 | "time",
23 | "timeEnd",
24 | "trace"
25 | ],
26 | "no-construct": true,
27 | "no-debugger": true,
28 | "no-duplicate-variable": true,
29 | "no-empty": false,
30 | "no-eval": true,
31 | "no-inferrable-types": true,
32 | "no-shadowed-variable": false,
33 | "no-string-literal": true,
34 | "no-switch-case-fall-through": true,
35 | "no-trailing-whitespace": true,
36 | "no-unused-expression": true,
37 | "no-use-before-declare": true,
38 | "no-var-keyword": false,
39 | "object-literal-sort-keys": true,
40 | "no-conditional-assignment": true,
41 | "one-line": [true,
42 | "check-open-brace",
43 | "check-catch",
44 | "check-else",
45 | "check-whitespace"
46 | ],
47 | "quotemark": [true, "single"],
48 | "radix": true,
49 | "semicolon": true,
50 | "triple-equals": [true, "allow-null-check"],
51 | "variable-name": [true,
52 | "check-format",
53 | "allow-leading-underscore"
54 | ],
55 | "whitespace": [true,
56 | "check-branch",
57 | "check-decl",
58 | "check-operator",
59 | "check-separator",
60 | "check-type"
61 | ]
62 | }
63 | }
64 |
--------------------------------------------------------------------------------